mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
Dump known material argument hashes
This commit is contained in:
parent
13c5ea2986
commit
7d2ca46cb1
@ -7,6 +7,20 @@ namespace IW4
|
|||||||
class Common
|
class Common
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static constexpr uint32_t R_HashString(const char* string, const uint32_t hash)
|
||||||
|
{
|
||||||
|
const char* v2 = string; // edx@1
|
||||||
|
char v3 = *string; // cl@1
|
||||||
|
uint32_t result = hash;
|
||||||
|
|
||||||
|
for (; *v2; v3 = *v2)
|
||||||
|
{
|
||||||
|
++v2;
|
||||||
|
result = 33 * result ^ (v3 | 0x20);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static int StringTable_HashString(const char* str);
|
static int StringTable_HashString(const char* str);
|
||||||
|
|
||||||
static PackedTexCoords Vec2PackTexCoords(const vec2_t* in);
|
static PackedTexCoords Vec2PackTexCoords(const vec2_t* in);
|
||||||
|
@ -1125,7 +1125,7 @@ namespace IW4
|
|||||||
struct CodeConstantSource
|
struct CodeConstantSource
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
unsigned char source;
|
MaterialConstantSource source;
|
||||||
CodeConstantSource* subtable;
|
CodeConstantSource* subtable;
|
||||||
int arrayCount;
|
int arrayCount;
|
||||||
int arrayStride;
|
int arrayStride;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "Game/IW4/CommonIW4.h"
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
|
|
||||||
namespace IW4
|
namespace IW4
|
||||||
@ -274,4 +276,58 @@ namespace IW4
|
|||||||
{"spotShadowmapPixelAdjust", CONST_SRC_CODE_SPOT_SHADOWMAP_PIXEL_ADJUST, nullptr, 0, 0},
|
{"spotShadowmapPixelAdjust", CONST_SRC_CODE_SPOT_SHADOWMAP_PIXEL_ADJUST, nullptr, 0, 0},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr std::pair<uint32_t, const char*> KnownMaterialSource(const char* name)
|
||||||
|
{
|
||||||
|
return std::make_pair(Common::R_HashString(name, 0u), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::unordered_map knownMaterialSourceNames
|
||||||
|
{
|
||||||
|
KnownMaterialSource("colorMap"),
|
||||||
|
KnownMaterialSource("colorMap0"),
|
||||||
|
KnownMaterialSource("colorMap1"),
|
||||||
|
KnownMaterialSource("colorMap2"),
|
||||||
|
KnownMaterialSource("colorMap3"),
|
||||||
|
KnownMaterialSource("colorMap4"),
|
||||||
|
KnownMaterialSource("colorMap5"),
|
||||||
|
KnownMaterialSource("colorMap6"),
|
||||||
|
KnownMaterialSource("colorMap7"),
|
||||||
|
KnownMaterialSource("normalMap"),
|
||||||
|
KnownMaterialSource("normalMap0"),
|
||||||
|
KnownMaterialSource("normalMap1"),
|
||||||
|
KnownMaterialSource("normalMap2"),
|
||||||
|
KnownMaterialSource("normalMap3"),
|
||||||
|
KnownMaterialSource("normalMap4"),
|
||||||
|
KnownMaterialSource("normalMap5"),
|
||||||
|
KnownMaterialSource("normalMap6"),
|
||||||
|
KnownMaterialSource("normalMap7"),
|
||||||
|
KnownMaterialSource("specularMap"),
|
||||||
|
KnownMaterialSource("specularMap0"),
|
||||||
|
KnownMaterialSource("specularMap1"),
|
||||||
|
KnownMaterialSource("specularMap2"),
|
||||||
|
KnownMaterialSource("specularMap3"),
|
||||||
|
KnownMaterialSource("specularMap4"),
|
||||||
|
KnownMaterialSource("specularMap5"),
|
||||||
|
KnownMaterialSource("specularMap6"),
|
||||||
|
KnownMaterialSource("specularMap7"),
|
||||||
|
KnownMaterialSource("detailMap"),
|
||||||
|
KnownMaterialSource("detailMap0"),
|
||||||
|
KnownMaterialSource("detailMap1"),
|
||||||
|
KnownMaterialSource("detailMap2"),
|
||||||
|
KnownMaterialSource("detailMap3"),
|
||||||
|
KnownMaterialSource("detailMap4"),
|
||||||
|
KnownMaterialSource("detailMap5"),
|
||||||
|
KnownMaterialSource("detailMap6"),
|
||||||
|
KnownMaterialSource("detailMap7"),
|
||||||
|
KnownMaterialSource("attenuationMap"),
|
||||||
|
KnownMaterialSource("attenuationMap0"),
|
||||||
|
KnownMaterialSource("attenuationMap1"),
|
||||||
|
KnownMaterialSource("attenuationMap2"),
|
||||||
|
KnownMaterialSource("attenuationMap3"),
|
||||||
|
KnownMaterialSource("attenuationMap4"),
|
||||||
|
KnownMaterialSource("attenuationMap5"),
|
||||||
|
KnownMaterialSource("attenuationMap6"),
|
||||||
|
KnownMaterialSource("attenuationMap7"),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,20 +13,82 @@
|
|||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
#include "Techset/TechniqueFileReader.h"
|
#include "Techset/TechniqueFileReader.h"
|
||||||
#include "Techset/TechsetFileReader.h"
|
#include "Techset/TechsetFileReader.h"
|
||||||
|
#include "Shader/D3D9ShaderAnalyser.h"
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
namespace IW4
|
namespace IW4
|
||||||
{
|
{
|
||||||
|
class LoadedTechnique
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaterialTechnique* m_technique;
|
||||||
|
std::vector<XAssetInfoGeneric*> m_dependencies;
|
||||||
|
|
||||||
|
LoadedTechnique(MaterialTechnique* technique, std::vector<XAssetInfoGeneric*> dependencies)
|
||||||
|
: m_technique(technique),
|
||||||
|
m_dependencies(std::move(dependencies))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TechniqueZoneLoadingState final : public IZoneAssetLoaderState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef const float (*literal_t)[4];
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, std::unique_ptr<LoadedTechnique>> m_loaded_techniques;
|
||||||
|
std::map<techset::ShaderArgumentLiteralSource, literal_t> m_allocated_literals;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_NODISCARD const LoadedTechnique* FindLoadedTechnique(const std::string& techniqueName) const
|
||||||
|
{
|
||||||
|
const auto loadedTechnique = m_loaded_techniques.find(techniqueName);
|
||||||
|
if (loadedTechnique != m_loaded_techniques.end())
|
||||||
|
return loadedTechnique->second.get();
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LoadedTechnique* AddLoadedTechnique(std::string techniqueName, MaterialTechnique* technique, std::vector<XAssetInfoGeneric*> dependencies)
|
||||||
|
{
|
||||||
|
return m_loaded_techniques.emplace(std::make_pair(std::move(techniqueName), std::make_unique<LoadedTechnique>(technique, std::move(dependencies)))).first->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
literal_t GetAllocatedLiteral(MemoryManager* memory, techset::ShaderArgumentLiteralSource source)
|
||||||
|
{
|
||||||
|
const auto& existingEntry = m_allocated_literals.find(source);
|
||||||
|
|
||||||
|
if (existingEntry != m_allocated_literals.end())
|
||||||
|
return existingEntry->second;
|
||||||
|
|
||||||
|
auto* newLiteral = static_cast<float(*)[4]>(memory->Alloc(sizeof(float) * 4u));
|
||||||
|
(*newLiteral)[0] = source.m_value[0];
|
||||||
|
(*newLiteral)[1] = source.m_value[1];
|
||||||
|
(*newLiteral)[2] = source.m_value[2];
|
||||||
|
(*newLiteral)[3] = source.m_value[3];
|
||||||
|
m_allocated_literals.emplace(std::make_pair(source, newLiteral));
|
||||||
|
|
||||||
|
return newLiteral;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class TechniqueCreator final : public techset::ITechniqueDefinitionAcceptor
|
class TechniqueCreator final : public techset::ITechniqueDefinitionAcceptor
|
||||||
{
|
{
|
||||||
|
MemoryManager* const m_memory;
|
||||||
IAssetLoadingManager* const m_manager;
|
IAssetLoadingManager* const m_manager;
|
||||||
|
TechniqueZoneLoadingState* const m_zone_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Pass
|
struct Pass
|
||||||
{
|
{
|
||||||
XAssetInfo<MaterialVertexShader>* m_vertex_shader;
|
XAssetInfo<MaterialVertexShader>* m_vertex_shader;
|
||||||
|
std::unique_ptr<d3d9::ShaderInfo> m_vertex_shader_info;
|
||||||
|
|
||||||
XAssetInfo<MaterialPixelShader>* m_pixel_shader;
|
XAssetInfo<MaterialPixelShader>* m_pixel_shader;
|
||||||
|
std::unique_ptr<d3d9::ShaderInfo> m_pixel_shader_info;
|
||||||
|
|
||||||
MaterialVertexDeclaration m_vertex_decl;
|
MaterialVertexDeclaration m_vertex_decl;
|
||||||
std::vector<MaterialShaderArgument> m_arguments;
|
std::vector<MaterialShaderArgument> m_arguments;
|
||||||
|
|
||||||
@ -41,8 +103,10 @@ namespace IW4
|
|||||||
std::vector<Pass> m_passes;
|
std::vector<Pass> m_passes;
|
||||||
std::vector<XAssetInfoGeneric*> m_dependencies;
|
std::vector<XAssetInfoGeneric*> m_dependencies;
|
||||||
|
|
||||||
explicit TechniqueCreator(IAssetLoadingManager* manager)
|
TechniqueCreator(MemoryManager* memory, IAssetLoadingManager* manager, TechniqueZoneLoadingState* zoneState)
|
||||||
: m_manager(manager)
|
: m_memory(memory),
|
||||||
|
m_manager(manager),
|
||||||
|
m_zone_state(zoneState)
|
||||||
{
|
{
|
||||||
m_passes.emplace_back();
|
m_passes.emplace_back();
|
||||||
}
|
}
|
||||||
@ -66,9 +130,13 @@ namespace IW4
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!m_passes.empty());
|
||||||
auto& pass = m_passes.at(m_passes.size() - 1);
|
auto& pass = m_passes.at(m_passes.size() - 1);
|
||||||
pass.m_vertex_shader = reinterpret_cast<XAssetInfo<MaterialVertexShader>*>(vertexShaderDependency);
|
pass.m_vertex_shader = reinterpret_cast<XAssetInfo<MaterialVertexShader>*>(vertexShaderDependency);
|
||||||
|
|
||||||
|
const auto& shaderLoadDef = pass.m_vertex_shader->Asset()->prog.loadDef;
|
||||||
|
pass.m_vertex_shader_info = d3d9::ShaderAnalyser::GetShaderInfo(shaderLoadDef.program, shaderLoadDef.programSize * sizeof(uint32_t));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,19 +149,295 @@ namespace IW4
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!m_passes.empty());
|
||||||
auto& pass = m_passes.at(m_passes.size() - 1);
|
auto& pass = m_passes.at(m_passes.size() - 1);
|
||||||
pass.m_pixel_shader = reinterpret_cast<XAssetInfo<MaterialPixelShader>*>(pixelShaderDependency);
|
pass.m_pixel_shader = reinterpret_cast<XAssetInfo<MaterialPixelShader>*>(pixelShaderDependency);
|
||||||
|
|
||||||
|
const auto& shaderLoadDef = pass.m_pixel_shader->Asset()->prog.loadDef;
|
||||||
|
pass.m_pixel_shader_info = d3d9::ShaderAnalyser::GetShaderInfo(shaderLoadDef.program, shaderLoadDef.programSize * sizeof(uint32_t));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AcceptShaderCodeArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentCodeSource source, std::string& errorMessage) override
|
static bool IsSamplerConstant(const d3d9::ShaderConstant& constant)
|
||||||
{
|
{
|
||||||
|
return constant.m_type == d3d9::ParameterType::SAMPLER
|
||||||
|
|| constant.m_type == d3d9::ParameterType::SAMPLER_1D
|
||||||
|
|| constant.m_type == d3d9::ParameterType::SAMPLER_2D
|
||||||
|
|| constant.m_type == d3d9::ParameterType::SAMPLER_3D
|
||||||
|
|| constant.m_type == d3d9::ParameterType::SAMPLER_CUBE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const CodeConstantSource* FindCodeConstantSource(const std::vector<std::string>& accessors, const CodeConstantSource* sourceTable)
|
||||||
|
{
|
||||||
|
const CodeConstantSource* foundSource = nullptr;
|
||||||
|
const CodeConstantSource* currentTable = sourceTable;
|
||||||
|
for (const auto& accessor : accessors)
|
||||||
|
{
|
||||||
|
if (currentTable == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (currentTable->name == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (accessor == currentTable->name)
|
||||||
|
break;
|
||||||
|
|
||||||
|
currentTable++;
|
||||||
|
}
|
||||||
|
|
||||||
|
foundSource = currentTable;
|
||||||
|
currentTable = currentTable->subtable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const CodeSamplerSource* FindCodeSamplerSource(const std::vector<std::string>& accessors, const CodeSamplerSource* sourceTable)
|
||||||
|
{
|
||||||
|
const CodeSamplerSource* foundSource = nullptr;
|
||||||
|
const CodeSamplerSource* currentTable = sourceTable;
|
||||||
|
for (const auto& accessor : accessors)
|
||||||
|
{
|
||||||
|
if (currentTable == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (currentTable->name == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (accessor == currentTable->name)
|
||||||
|
break;
|
||||||
|
|
||||||
|
currentTable++;
|
||||||
|
}
|
||||||
|
|
||||||
|
foundSource = currentTable;
|
||||||
|
currentTable = currentTable->subtable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AcceptVertexShaderCodeArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage)
|
||||||
|
{
|
||||||
|
assert(!m_passes.empty());
|
||||||
|
auto& pass = m_passes.at(m_passes.size() - 1);
|
||||||
|
|
||||||
|
if (!pass.m_vertex_shader_info)
|
||||||
|
{
|
||||||
|
errorMessage = "Shader not specified";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& shaderInfo = *pass.m_vertex_shader_info;
|
||||||
|
const auto matchingShaderConstant = std::find_if(shaderInfo.m_constants.begin(), shaderInfo.m_constants.end(), [&shaderArgument](const d3d9::ShaderConstant& constant)
|
||||||
|
{
|
||||||
|
return constant.m_name == shaderArgument.m_argument_name;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (matchingShaderConstant == shaderInfo.m_constants.end())
|
||||||
|
{
|
||||||
|
errorMessage = "Could not find argument in shader";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto constantIsSampler = IsSamplerConstant(*matchingShaderConstant);
|
||||||
|
if (constantIsSampler)
|
||||||
|
{
|
||||||
|
errorMessage = "Vertex sampler are unsupported";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialShaderArgument argument{};
|
||||||
|
argument.type = MTL_ARG_CODE_VERTEX_CONST;
|
||||||
|
argument.dest = static_cast<uint16_t>(matchingShaderConstant->m_register_index);
|
||||||
|
|
||||||
|
const CodeConstantSource* constantSource = FindCodeConstantSource(source.m_accessors, s_codeConsts);
|
||||||
|
if (!constantSource)
|
||||||
|
constantSource = FindCodeConstantSource(source.m_accessors, s_defaultCodeConsts);
|
||||||
|
|
||||||
|
if (!constantSource)
|
||||||
|
{
|
||||||
|
errorMessage = "Unknown code constant";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constantSource->arrayCount > 0)
|
||||||
|
{
|
||||||
|
if (!source.m_index_accessor_specified)
|
||||||
|
{
|
||||||
|
errorMessage = "Code constant must have array index specified";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.m_index_accessor >= static_cast<size_t>(constantSource->arrayCount))
|
||||||
|
{
|
||||||
|
errorMessage = "Code constant array index out of bounds";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
argument.u.codeConst.index = static_cast<uint16_t>(constantSource->source + source.m_index_accessor);
|
||||||
|
}
|
||||||
|
else if (source.m_index_accessor_specified)
|
||||||
|
{
|
||||||
|
errorMessage = "Code constant cannot have array index specified";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argument.u.codeConst.index = static_cast<uint16_t>(constantSource->source);
|
||||||
|
}
|
||||||
|
argument.u.codeConst.firstRow = 0u;
|
||||||
|
argument.u.codeConst.rowCount = static_cast<unsigned char>(matchingShaderConstant->m_type_rows);
|
||||||
|
|
||||||
|
pass.m_arguments.push_back(argument);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AcceptShaderLiteralArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) override
|
bool AcceptPixelShaderCodeArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage)
|
||||||
{
|
{
|
||||||
|
assert(!m_passes.empty());
|
||||||
|
auto& pass = m_passes.at(m_passes.size() - 1);
|
||||||
|
|
||||||
|
if (!pass.m_pixel_shader_info)
|
||||||
|
{
|
||||||
|
errorMessage = "Shader not specified";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& shaderInfo = *pass.m_pixel_shader_info;
|
||||||
|
|
||||||
|
const auto matchingShaderConstant = std::find_if(shaderInfo.m_constants.begin(), shaderInfo.m_constants.end(), [&shaderArgument](const d3d9::ShaderConstant& constant)
|
||||||
|
{
|
||||||
|
return constant.m_name == shaderArgument.m_argument_name;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (matchingShaderConstant == shaderInfo.m_constants.end())
|
||||||
|
{
|
||||||
|
errorMessage = "Could not find argument in shader";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto constantIsSampler = IsSamplerConstant(*matchingShaderConstant);
|
||||||
|
MaterialShaderArgument argument{};
|
||||||
|
argument.type = constantIsSampler ? MTL_ARG_CODE_PIXEL_SAMPLER : MTL_ARG_CODE_PIXEL_CONST;
|
||||||
|
argument.dest = static_cast<uint16_t>(matchingShaderConstant->m_register_index);
|
||||||
|
|
||||||
|
unsigned sourceIndex, arrayCount;
|
||||||
|
if (constantIsSampler)
|
||||||
|
{
|
||||||
|
const CodeSamplerSource* samplerSource = FindCodeSamplerSource(source.m_accessors, s_codeSamplers);
|
||||||
|
if (!samplerSource)
|
||||||
|
samplerSource = FindCodeSamplerSource(source.m_accessors, s_defaultCodeSamplers);
|
||||||
|
|
||||||
|
if (!samplerSource)
|
||||||
|
{
|
||||||
|
errorMessage = "Unknown code sampler";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceIndex = static_cast<unsigned>(samplerSource->source);
|
||||||
|
arrayCount = static_cast<unsigned>(samplerSource->arrayCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const CodeConstantSource* constantSource = FindCodeConstantSource(source.m_accessors, s_codeConsts);
|
||||||
|
if (!constantSource)
|
||||||
|
constantSource = FindCodeConstantSource(source.m_accessors, s_defaultCodeConsts);
|
||||||
|
|
||||||
|
if (!constantSource)
|
||||||
|
{
|
||||||
|
errorMessage = "Unknown code constant";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceIndex = static_cast<unsigned>(constantSource->source);
|
||||||
|
arrayCount = static_cast<unsigned>(constantSource->arrayCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrayCount > 0u)
|
||||||
|
{
|
||||||
|
if (!source.m_index_accessor_specified)
|
||||||
|
{
|
||||||
|
errorMessage = "Code constant must have array index specified";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.m_index_accessor >= arrayCount)
|
||||||
|
{
|
||||||
|
errorMessage = "Code constant array index out of bounds";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
argument.u.codeConst.index = static_cast<uint16_t>(sourceIndex + source.m_index_accessor);
|
||||||
|
}
|
||||||
|
else if (source.m_index_accessor_specified)
|
||||||
|
{
|
||||||
|
errorMessage = "Code constant cannot have array index specified";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argument.u.codeConst.index = static_cast<uint16_t>(sourceIndex);
|
||||||
|
}
|
||||||
|
argument.u.codeConst.firstRow = 0u;
|
||||||
|
argument.u.codeConst.rowCount = static_cast<unsigned char>(matchingShaderConstant->m_type_rows);
|
||||||
|
|
||||||
|
pass.m_arguments.push_back(argument);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AcceptShaderCodeArgument(const techset::ShaderSelector shader, const techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource source,
|
||||||
|
std::string& errorMessage) override
|
||||||
|
{
|
||||||
|
if (shader == techset::ShaderSelector::VERTEX_SHADER)
|
||||||
|
return AcceptVertexShaderCodeArgument(shaderArgument, source, errorMessage);
|
||||||
|
|
||||||
|
assert(shader == techset::ShaderSelector::PIXEL_SHADER);
|
||||||
|
return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AcceptShaderLiteralArgument(const techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) override
|
||||||
|
{
|
||||||
|
assert(!m_passes.empty());
|
||||||
|
auto& pass = m_passes.at(m_passes.size() - 1);
|
||||||
|
|
||||||
|
MaterialShaderArgument argument{};
|
||||||
|
const d3d9::ShaderInfo* shaderInfo;
|
||||||
|
|
||||||
|
if (shader == techset::ShaderSelector::VERTEX_SHADER)
|
||||||
|
{
|
||||||
|
argument.type = MTL_ARG_LITERAL_VERTEX_CONST;
|
||||||
|
shaderInfo = pass.m_vertex_shader_info.get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(shader == techset::ShaderSelector::PIXEL_SHADER);
|
||||||
|
argument.type = MTL_ARG_LITERAL_PIXEL_CONST;
|
||||||
|
shaderInfo = pass.m_pixel_shader_info.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shaderInfo)
|
||||||
|
{
|
||||||
|
errorMessage = "Shader not specified";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto matchingShaderConstant = std::find_if(shaderInfo->m_constants.begin(), shaderInfo->m_constants.end(), [&shaderArgument](const d3d9::ShaderConstant& constant)
|
||||||
|
{
|
||||||
|
return constant.m_name == shaderArgument.m_argument_name;
|
||||||
|
});
|
||||||
|
|
||||||
|
argument.dest = static_cast<uint16_t>(matchingShaderConstant->m_register_index);
|
||||||
|
argument.u.literalConst = m_zone_state->GetAllocatedLiteral(m_memory, source);
|
||||||
|
pass.m_arguments.push_back(argument);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,39 +452,6 @@ namespace IW4
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoadedTechnique
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MaterialTechnique* m_technique;
|
|
||||||
std::vector<XAssetInfoGeneric*> m_dependencies;
|
|
||||||
|
|
||||||
LoadedTechnique(MaterialTechnique* technique, std::vector<XAssetInfoGeneric*> dependencies)
|
|
||||||
: m_technique(technique),
|
|
||||||
m_dependencies(std::move(dependencies))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TechniqueZoneLoadingState final : public IZoneAssetLoaderState
|
|
||||||
{
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<LoadedTechnique>> m_loaded_techniques;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_NODISCARD const LoadedTechnique* FindLoadedTechnique(const std::string& techniqueName) const
|
|
||||||
{
|
|
||||||
const auto loadedTechnique = m_loaded_techniques.find(techniqueName);
|
|
||||||
if (loadedTechnique != m_loaded_techniques.end())
|
|
||||||
return loadedTechnique->second.get();
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoadedTechnique* AddLoadedTechnique(std::string techniqueName, MaterialTechnique* technique, std::vector<XAssetInfoGeneric*> dependencies)
|
|
||||||
{
|
|
||||||
return m_loaded_techniques.emplace(std::make_pair(std::move(techniqueName), std::make_unique<LoadedTechnique>(technique, std::move(dependencies)))).first->second.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TechniqueLoader
|
class TechniqueLoader
|
||||||
{
|
{
|
||||||
ISearchPath* m_search_path;
|
ISearchPath* m_search_path;
|
||||||
@ -155,6 +466,28 @@ namespace IW4
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConvertPass(MaterialPass& out, const TechniqueCreator::Pass& in)
|
||||||
|
{
|
||||||
|
out.vertexShader = in.m_vertex_shader->Asset();
|
||||||
|
out.pixelShader = in.m_pixel_shader->Asset();
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialTechnique* ConvertTechnique(const std::string& techniqueName, const std::vector<TechniqueCreator::Pass>& passes)
|
||||||
|
{
|
||||||
|
assert(!passes.empty());
|
||||||
|
// TODO: Load technique or use previously loaded one
|
||||||
|
const auto techniqueSize = sizeof(MaterialTechnique) + (passes.size() - 1u) * sizeof(MaterialPass);
|
||||||
|
auto* technique = static_cast<MaterialTechnique*>(m_memory->Alloc(techniqueSize));
|
||||||
|
memset(technique, 0, techniqueSize);
|
||||||
|
technique->name = m_memory->Dup(techniqueName.c_str());
|
||||||
|
technique->passCount = static_cast<uint16_t>(passes.size());
|
||||||
|
|
||||||
|
for (auto i = 0u; i < passes.size(); i++)
|
||||||
|
ConvertPass(technique->passArray[i], passes.at(i));
|
||||||
|
|
||||||
|
return technique;
|
||||||
|
}
|
||||||
|
|
||||||
MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector<XAssetInfoGeneric*>& dependencies)
|
MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector<XAssetInfoGeneric*>& dependencies)
|
||||||
{
|
{
|
||||||
const auto techniqueFileName = GetTechniqueFileName(techniqueName);
|
const auto techniqueFileName = GetTechniqueFileName(techniqueName);
|
||||||
@ -162,12 +495,12 @@ namespace IW4
|
|||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
TechniqueCreator creator(m_manager);
|
TechniqueCreator creator(m_memory, m_manager, m_zone_state);
|
||||||
techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator);
|
const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator);
|
||||||
if (!reader.ReadTechniqueDefinition())
|
if (!reader.ReadTechniqueDefinition())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
// TODO: Load technique or use previously loaded one
|
|
||||||
return nullptr;
|
return ConvertTechnique(techniqueName, creator.m_passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -187,7 +520,7 @@ namespace IW4
|
|||||||
|
|
||||||
std::vector<XAssetInfoGeneric*> dependencies;
|
std::vector<XAssetInfoGeneric*> dependencies;
|
||||||
auto* techniqueFromRaw = LoadTechniqueFromRaw(techniqueName, dependencies);
|
auto* techniqueFromRaw = LoadTechniqueFromRaw(techniqueName, dependencies);
|
||||||
if (technique == nullptr)
|
if (techniqueFromRaw == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return m_zone_state->AddLoadedTechnique(techniqueName, techniqueFromRaw, dependencies);
|
return m_zone_state->AddLoadedTechnique(techniqueName, techniqueFromRaw, dependencies);
|
||||||
|
@ -61,18 +61,26 @@ namespace techset
|
|||||||
}).Tag(TAG_CODE);
|
}).Tag(TAG_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<matcher_t> LiteralValueMatchers(const SimpleMatcherFactory& create)
|
||||||
|
{
|
||||||
|
return create.Or({
|
||||||
|
create.FloatingPoint(),
|
||||||
|
create.Integer()
|
||||||
|
}).Capture(CAPTURE_LITERAL_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
static std::unique_ptr<matcher_t> LiteralMatchers(const SimpleMatcherFactory& create)
|
static std::unique_ptr<matcher_t> LiteralMatchers(const SimpleMatcherFactory& create)
|
||||||
{
|
{
|
||||||
return create.And({
|
return create.And({
|
||||||
create.Keyword("float4"),
|
create.Keyword("float4"),
|
||||||
create.Char('('),
|
create.Char('('),
|
||||||
create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE),
|
LiteralValueMatchers(create),
|
||||||
create.Char(','),
|
create.Char(','),
|
||||||
create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE),
|
LiteralValueMatchers(create),
|
||||||
create.Char(','),
|
create.Char(','),
|
||||||
create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE),
|
LiteralValueMatchers(create),
|
||||||
create.Char(','),
|
create.Char(','),
|
||||||
create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE),
|
LiteralValueMatchers(create),
|
||||||
create.Char(')'),
|
create.Char(')'),
|
||||||
}).Tag(TAG_LITERAL);
|
}).Tag(TAG_LITERAL);
|
||||||
}
|
}
|
||||||
@ -142,7 +150,14 @@ namespace techset
|
|||||||
{
|
{
|
||||||
float value[4];
|
float value[4];
|
||||||
for (float& i : value)
|
for (float& i : value)
|
||||||
i = static_cast<float>(result.NextCapture(CAPTURE_LITERAL_VALUE).FloatingPointValue());
|
{
|
||||||
|
const auto& literalValueToken = result.NextCapture(CAPTURE_LITERAL_VALUE);
|
||||||
|
|
||||||
|
if (literalValueToken.m_type == SimpleParserValueType::FLOATING_POINT)
|
||||||
|
i = static_cast<float>(literalValueToken.FloatingPointValue());
|
||||||
|
else
|
||||||
|
i = static_cast<float>(literalValueToken.IntegerValue());
|
||||||
|
}
|
||||||
|
|
||||||
const ShaderArgumentLiteralSource source(value);
|
const ShaderArgumentLiteralSource source(value);
|
||||||
std::string errorMessage;
|
std::string errorMessage;
|
||||||
@ -174,16 +189,17 @@ namespace techset
|
|||||||
|
|
||||||
const auto& shaderArgumentNameToken = result.NextCapture(CAPTURE_SHADER_ARGUMENT);
|
const auto& shaderArgumentNameToken = result.NextCapture(CAPTURE_SHADER_ARGUMENT);
|
||||||
|
|
||||||
size_t index = 0u;
|
ShaderArgument arg;
|
||||||
if (result.HasNextCapture(CAPTURE_SHADER_INDEX))
|
if (result.HasNextCapture(CAPTURE_SHADER_INDEX))
|
||||||
{
|
{
|
||||||
const auto& shaderArgumentIndexToken = result.NextCapture(CAPTURE_SHADER_INDEX);
|
const auto& shaderArgumentIndexToken = result.NextCapture(CAPTURE_SHADER_INDEX);
|
||||||
if (shaderArgumentIndexToken.IntegerValue() < 0)
|
if (shaderArgumentIndexToken.IntegerValue() < 0)
|
||||||
throw ParsingException(shaderArgumentIndexToken.GetPos(), "Index cannot be negative");
|
throw ParsingException(shaderArgumentIndexToken.GetPos(), "Index cannot be negative");
|
||||||
index = static_cast<size_t>(shaderArgumentIndexToken.IntegerValue());
|
const auto index = static_cast<size_t>(shaderArgumentIndexToken.IntegerValue());
|
||||||
|
arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue(), index);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
ShaderArgument arg(shaderArgumentNameToken.IdentifierValue(), index);
|
arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue());
|
||||||
|
|
||||||
const auto typeTag = result.NextTag();
|
const auto typeTag = result.NextTag();
|
||||||
assert(typeTag == TAG_CODE || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL);
|
assert(typeTag == TAG_CODE || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL);
|
||||||
|
@ -3,12 +3,21 @@
|
|||||||
using namespace techset;
|
using namespace techset;
|
||||||
|
|
||||||
ShaderArgument::ShaderArgument()
|
ShaderArgument::ShaderArgument()
|
||||||
: m_argument_index(0u)
|
: m_argument_index_specified(false),
|
||||||
|
m_argument_index(0u)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderArgument::ShaderArgument(std::string argumentName)
|
||||||
|
: m_argument_name(std::move(argumentName)),
|
||||||
|
m_argument_index_specified(false),
|
||||||
|
m_argument_index(0u)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderArgument::ShaderArgument(std::string argumentName, const size_t argumentIndex)
|
ShaderArgument::ShaderArgument(std::string argumentName, const size_t argumentIndex)
|
||||||
: m_argument_name(std::move(argumentName)),
|
: m_argument_name(std::move(argumentName)),
|
||||||
|
m_argument_index_specified(true),
|
||||||
m_argument_index(argumentIndex)
|
m_argument_index(argumentIndex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,11 @@ namespace techset
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string m_argument_name;
|
std::string m_argument_name;
|
||||||
|
bool m_argument_index_specified;
|
||||||
size_t m_argument_index;
|
size_t m_argument_index;
|
||||||
|
|
||||||
ShaderArgument();
|
ShaderArgument();
|
||||||
|
explicit ShaderArgument(std::string argumentName);
|
||||||
ShaderArgument(std::string argumentName, size_t argumentIndex);
|
ShaderArgument(std::string argumentName, size_t argumentIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ namespace IW4
|
|||||||
}
|
}
|
||||||
else if (currentCodeConst->arrayCount > 0)
|
else if (currentCodeConst->arrayCount > 0)
|
||||||
{
|
{
|
||||||
if (currentCodeConst->source <= static_cast<unsigned>(sourceIndexToFind)
|
if (currentCodeConst->source <= sourceIndexToFind
|
||||||
&& static_cast<unsigned>(currentCodeConst->source) + currentCodeConst->arrayCount > static_cast<unsigned>(sourceIndexToFind))
|
&& static_cast<unsigned>(currentCodeConst->source) + currentCodeConst->arrayCount > static_cast<unsigned>(sourceIndexToFind))
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
@ -150,13 +150,13 @@ namespace IW4
|
|||||||
if (codeDestAccessor != codeSourceAccessor)
|
if (codeDestAccessor != codeSourceAccessor)
|
||||||
{
|
{
|
||||||
Indent();
|
Indent();
|
||||||
m_stream << codeDestAccessor << " = code." << codeSourceAccessor << ";\n";
|
m_stream << codeDestAccessor << " = constant." << codeSourceAccessor << ";\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef TECHSET_DEBUG
|
#ifdef TECHSET_DEBUG
|
||||||
Indent();
|
Indent();
|
||||||
m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = code." << codeSourceAccessor << ";\n";
|
m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = constant." << codeSourceAccessor << ";\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,13 +177,13 @@ namespace IW4
|
|||||||
if (codeDestAccessor != codeSourceAccessor)
|
if (codeDestAccessor != codeSourceAccessor)
|
||||||
{
|
{
|
||||||
Indent();
|
Indent();
|
||||||
m_stream << codeDestAccessor << " = code." << codeSourceAccessor << ";\n";
|
m_stream << codeDestAccessor << " = sampler." << codeSourceAccessor << ";\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef TECHSET_DEBUG
|
#ifdef TECHSET_DEBUG
|
||||||
Indent();
|
Indent();
|
||||||
m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = code." << codeSourceAccessor << ";\n";
|
m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = sampler." << codeSourceAccessor << ";\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +209,23 @@ namespace IW4
|
|||||||
else if (arg.type == MTL_ARG_MATERIAL_PIXEL_CONST || arg.type == MTL_ARG_MATERIAL_VERTEX_CONST || arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER)
|
else if (arg.type == MTL_ARG_MATERIAL_PIXEL_CONST || arg.type == MTL_ARG_MATERIAL_VERTEX_CONST || arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER)
|
||||||
{
|
{
|
||||||
Indent();
|
Indent();
|
||||||
m_stream << codeDestAccessor << " = material.#0x" << std::hex << arg.u.nameHash << ";\n";
|
m_stream << codeDestAccessor << " = material.";
|
||||||
|
|
||||||
|
const auto knownMaterialSource = knownMaterialSourceNames.find(arg.u.nameHash);
|
||||||
|
if (knownMaterialSource != knownMaterialSourceNames.end())
|
||||||
|
{
|
||||||
|
m_stream << knownMaterialSource->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto shaderArgNameHash = Common::R_HashString(targetShaderArg->m_name.c_str(), 0u);
|
||||||
|
if (shaderArgNameHash == arg.u.nameHash)
|
||||||
|
m_stream << targetShaderArg->m_name;
|
||||||
|
else
|
||||||
|
m_stream << "#0x" << std::hex << arg.u.nameHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_stream << ";\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -228,7 +244,7 @@ namespace IW4
|
|||||||
{
|
{
|
||||||
const auto loadedVertexShaderFromOtherZone = GlobalAssetPool<MaterialVertexShader>::GetAssetByName(&vertexShader->name[1]);
|
const auto loadedVertexShaderFromOtherZone = GlobalAssetPool<MaterialVertexShader>::GetAssetByName(&vertexShader->name[1]);
|
||||||
|
|
||||||
if(loadedVertexShaderFromOtherZone == nullptr)
|
if (loadedVertexShaderFromOtherZone == nullptr)
|
||||||
{
|
{
|
||||||
// Cannot dump when shader is referenced due to unknown constant names and unknown version
|
// Cannot dump when shader is referenced due to unknown constant names and unknown version
|
||||||
Indent();
|
Indent();
|
||||||
@ -387,7 +403,7 @@ namespace IW4
|
|||||||
if (vertexDecl == nullptr)
|
if (vertexDecl == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(vertexDecl->name && vertexDecl->name[0] == ',')
|
if (vertexDecl->name && vertexDecl->name[0] == ',')
|
||||||
{
|
{
|
||||||
const auto loadedVertexDeclFromOtherZone = GlobalAssetPool<MaterialVertexDeclaration>::GetAssetByName(&vertexDecl->name[1]);
|
const auto loadedVertexDeclFromOtherZone = GlobalAssetPool<MaterialVertexDeclaration>::GetAssetByName(&vertexDecl->name[1]);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user