mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
Merge pull request #126 from Laupetin/feature/dx11-shader-parsing
feat: use parameter names from dx11 shaders to resolve material hashes
This commit is contained in:
commit
99632f5d98
685
src/ObjCommon/Shader/D3D11ShaderAnalyser.cpp
Normal file
685
src/ObjCommon/Shader/D3D11ShaderAnalyser.cpp
Normal file
@ -0,0 +1,685 @@
|
|||||||
|
#include "D3D11ShaderAnalyser.h"
|
||||||
|
|
||||||
|
#include "Utils/FileUtils.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace d3d11;
|
||||||
|
|
||||||
|
namespace d3d11
|
||||||
|
{
|
||||||
|
BoundResource::BoundResource()
|
||||||
|
: m_type(BoundResourceType::UNKNOWN),
|
||||||
|
m_return_type(BoundResourceReturnType::UNKNOWN),
|
||||||
|
m_dimension(BoundResourceDimension::UNKNOWN),
|
||||||
|
m_num_samples(0u),
|
||||||
|
m_bind_point(0u),
|
||||||
|
m_bind_count(0u),
|
||||||
|
m_flags(0u)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantBuffer::ConstantBuffer()
|
||||||
|
: m_size(0u),
|
||||||
|
m_flags(0u),
|
||||||
|
m_type(ConstantBufferType::UNKNOWN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantBufferVariable::ConstantBufferVariable()
|
||||||
|
: m_offset(0u),
|
||||||
|
m_size(0u),
|
||||||
|
m_flags(0u)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto TAG_RDEF = FileUtils::MakeMagic32('R', 'D', 'E', 'F');
|
||||||
|
static constexpr auto TAG_SHDR = FileUtils::MakeMagic32('S', 'H', 'D', 'R');
|
||||||
|
|
||||||
|
static constexpr auto VERSION_5_0 = 0x500;
|
||||||
|
static constexpr auto VERSION_5_1 = 0x501;
|
||||||
|
static constexpr auto TARGET_VERSION_MASK = 0xFFFF;
|
||||||
|
static constexpr auto CHUNK_TABLE_OFFSET = 28u;
|
||||||
|
|
||||||
|
struct FileRdefHeader
|
||||||
|
{
|
||||||
|
uint32_t constantBufferCount;
|
||||||
|
uint32_t constantBufferOffset;
|
||||||
|
uint32_t boundResourceCount;
|
||||||
|
uint32_t boundResourceOffset;
|
||||||
|
uint32_t target;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t creatorOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileRdefExtraHeader_5_0
|
||||||
|
{
|
||||||
|
// Wine project does not seem to know what this is
|
||||||
|
uint32_t unknown[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(FileRdefHeader) == 28);
|
||||||
|
static_assert(sizeof(FileRdefExtraHeader_5_0) == 32);
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_shader_input_type
|
||||||
|
enum D3D_SHADER_INPUT_TYPE : uint32_t
|
||||||
|
{
|
||||||
|
D3D_SIT_CBUFFER = 0,
|
||||||
|
D3D_SIT_TBUFFER,
|
||||||
|
D3D_SIT_TEXTURE,
|
||||||
|
D3D_SIT_SAMPLER,
|
||||||
|
D3D_SIT_UAV_RWTYPED,
|
||||||
|
D3D_SIT_STRUCTURED,
|
||||||
|
D3D_SIT_UAV_RWSTRUCTURED,
|
||||||
|
D3D_SIT_BYTEADDRESS,
|
||||||
|
D3D_SIT_UAV_RWBYTEADDRESS,
|
||||||
|
D3D_SIT_UAV_APPEND_STRUCTURED,
|
||||||
|
D3D_SIT_UAV_CONSUME_STRUCTURED,
|
||||||
|
D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER,
|
||||||
|
D3D_SIT_RTACCELERATIONSTRUCTURE,
|
||||||
|
D3D_SIT_UAV_FEEDBACKTEXTURE,
|
||||||
|
D3D10_SIT_CBUFFER,
|
||||||
|
D3D10_SIT_TBUFFER,
|
||||||
|
D3D10_SIT_TEXTURE,
|
||||||
|
D3D10_SIT_SAMPLER,
|
||||||
|
D3D11_SIT_UAV_RWTYPED,
|
||||||
|
D3D11_SIT_STRUCTURED,
|
||||||
|
D3D11_SIT_UAV_RWSTRUCTURED,
|
||||||
|
D3D11_SIT_BYTEADDRESS,
|
||||||
|
D3D11_SIT_UAV_RWBYTEADDRESS,
|
||||||
|
D3D11_SIT_UAV_APPEND_STRUCTURED,
|
||||||
|
D3D11_SIT_UAV_CONSUME_STRUCTURED,
|
||||||
|
D3D11_SIT_UAV_RWSTRUCTURED_WITH_COUNTER
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_resource_return_type
|
||||||
|
enum D3D_RESOURCE_RETURN_TYPE : uint32_t
|
||||||
|
{
|
||||||
|
D3D_RETURN_TYPE_UNORM = 1,
|
||||||
|
D3D_RETURN_TYPE_SNORM = 2,
|
||||||
|
D3D_RETURN_TYPE_SINT = 3,
|
||||||
|
D3D_RETURN_TYPE_UINT = 4,
|
||||||
|
D3D_RETURN_TYPE_FLOAT = 5,
|
||||||
|
D3D_RETURN_TYPE_MIXED = 6,
|
||||||
|
D3D_RETURN_TYPE_DOUBLE = 7,
|
||||||
|
D3D_RETURN_TYPE_CONTINUED = 8,
|
||||||
|
D3D10_RETURN_TYPE_UNORM,
|
||||||
|
D3D10_RETURN_TYPE_SNORM,
|
||||||
|
D3D10_RETURN_TYPE_SINT,
|
||||||
|
D3D10_RETURN_TYPE_UINT,
|
||||||
|
D3D10_RETURN_TYPE_FLOAT,
|
||||||
|
D3D10_RETURN_TYPE_MIXED,
|
||||||
|
D3D11_RETURN_TYPE_UNORM,
|
||||||
|
D3D11_RETURN_TYPE_SNORM,
|
||||||
|
D3D11_RETURN_TYPE_SINT,
|
||||||
|
D3D11_RETURN_TYPE_UINT,
|
||||||
|
D3D11_RETURN_TYPE_FLOAT,
|
||||||
|
D3D11_RETURN_TYPE_MIXED,
|
||||||
|
D3D11_RETURN_TYPE_DOUBLE,
|
||||||
|
D3D11_RETURN_TYPE_CONTINUED
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_srv_dimension
|
||||||
|
enum D3D_SRV_DIMENSION : uint32_t
|
||||||
|
{
|
||||||
|
D3D_SRV_DIMENSION_UNKNOWN = 0,
|
||||||
|
D3D_SRV_DIMENSION_BUFFER = 1,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURE1D = 2,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURE1DARRAY = 3,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURE2D = 4,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURE2DARRAY = 5,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURE2DMS = 6,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURE2DMSARRAY = 7,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURE3D = 8,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURECUBE = 9,
|
||||||
|
D3D_SRV_DIMENSION_TEXTURECUBEARRAY = 10,
|
||||||
|
D3D_SRV_DIMENSION_BUFFEREX = 11,
|
||||||
|
D3D10_SRV_DIMENSION_UNKNOWN,
|
||||||
|
D3D10_SRV_DIMENSION_BUFFER,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURE1D,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURE1DARRAY,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURE2D,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURE2DARRAY,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURE2DMS,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURE3D,
|
||||||
|
D3D10_SRV_DIMENSION_TEXTURECUBE,
|
||||||
|
D3D10_1_SRV_DIMENSION_UNKNOWN,
|
||||||
|
D3D10_1_SRV_DIMENSION_BUFFER,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURE1D,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURE1DARRAY,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURE2D,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURE2DARRAY,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURE2DMS,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURE2DMSARRAY,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURE3D,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURECUBE,
|
||||||
|
D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY,
|
||||||
|
D3D11_SRV_DIMENSION_UNKNOWN,
|
||||||
|
D3D11_SRV_DIMENSION_BUFFER,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURE1D,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURE1DARRAY,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURE2D,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURE2DARRAY,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURE2DMS,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURE3D,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURECUBE,
|
||||||
|
D3D11_SRV_DIMENSION_TEXTURECUBEARRAY,
|
||||||
|
D3D11_SRV_DIMENSION_BUFFEREX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileBoundResource
|
||||||
|
{
|
||||||
|
uint32_t nameOffset;
|
||||||
|
D3D_SHADER_INPUT_TYPE type;
|
||||||
|
D3D_RESOURCE_RETURN_TYPE returnType;
|
||||||
|
D3D_SRV_DIMENSION dimension;
|
||||||
|
uint32_t numSamples;
|
||||||
|
uint32_t bindPoint;
|
||||||
|
uint32_t bindCount;
|
||||||
|
uint32_t uFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileBoundResource_5_1 : FileBoundResource
|
||||||
|
{
|
||||||
|
uint32_t space;
|
||||||
|
uint32_t uID;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(FileBoundResource) == 32);
|
||||||
|
static_assert(sizeof(FileBoundResource_5_1) == 40);
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_cbuffer_type
|
||||||
|
enum D3D_CBUFFER_TYPE : uint32_t
|
||||||
|
{
|
||||||
|
D3D_CT_CBUFFER = 0,
|
||||||
|
D3D_CT_TBUFFER,
|
||||||
|
D3D_CT_INTERFACE_POINTERS,
|
||||||
|
D3D_CT_RESOURCE_BIND_INFO,
|
||||||
|
D3D10_CT_CBUFFER,
|
||||||
|
D3D10_CT_TBUFFER,
|
||||||
|
D3D11_CT_CBUFFER,
|
||||||
|
D3D11_CT_TBUFFER,
|
||||||
|
D3D11_CT_INTERFACE_POINTERS,
|
||||||
|
D3D11_CT_RESOURCE_BIND_INFO
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileConstantBuffer
|
||||||
|
{
|
||||||
|
uint32_t nameOffset;
|
||||||
|
uint32_t variableCount;
|
||||||
|
uint32_t variableOffset;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t flags;
|
||||||
|
D3D_CBUFFER_TYPE type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileConstantBufferVariable
|
||||||
|
{
|
||||||
|
uint32_t nameOffset;
|
||||||
|
uint32_t startOffset;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t typeOffset;
|
||||||
|
uint32_t defaultValueOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileConstantBufferVariable_5_0 : FileConstantBufferVariable
|
||||||
|
{
|
||||||
|
// Wine project does not seem to know what this is
|
||||||
|
uint32_t unknown[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(FileConstantBufferVariable) == 24);
|
||||||
|
static_assert(sizeof(FileConstantBufferVariable_5_0) == 40);
|
||||||
|
|
||||||
|
enum FileProgramType : uint32_t
|
||||||
|
{
|
||||||
|
D3D10_SB_PIXEL_SHADER = 0,
|
||||||
|
D3D10_SB_VERTEX_SHADER = 1,
|
||||||
|
D3D10_SB_GEOMETRY_SHADER = 2,
|
||||||
|
|
||||||
|
// D3D11 Shaders
|
||||||
|
D3D11_SB_HULL_SHADER = 3,
|
||||||
|
D3D11_SB_DOMAIN_SHADER = 4,
|
||||||
|
D3D11_SB_COMPUTE_SHADER = 5,
|
||||||
|
|
||||||
|
D3D11_SB_RESERVED0 = 0xFFF0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileShaderHeader
|
||||||
|
{
|
||||||
|
uint32_t versionMinor : 4;
|
||||||
|
uint32_t versionMajor : 4;
|
||||||
|
uint32_t unused : 8;
|
||||||
|
FileProgramType programType : 16;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(FileShaderHeader) == 4);
|
||||||
|
|
||||||
|
uint32_t ReadU32(const uint8_t*& ptr)
|
||||||
|
{
|
||||||
|
const auto result = *reinterpret_cast<const uint32_t*>(ptr);
|
||||||
|
ptr += sizeof(uint32_t);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindChunk(const uint32_t magic, const uint8_t* byteCode, const size_t byteCodeSize, size_t& chunkOffset, size_t& chunkSize)
|
||||||
|
{
|
||||||
|
if (byteCodeSize < CHUNK_TABLE_OFFSET + sizeof(uint32_t))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto* ptr = byteCode + CHUNK_TABLE_OFFSET;
|
||||||
|
const auto chunkCount = ReadU32(ptr);
|
||||||
|
if (byteCodeSize < (ptr - byteCode) + chunkCount * sizeof(uint32_t))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto chunkIndex = 0u; chunkIndex < chunkCount; chunkIndex++)
|
||||||
|
{
|
||||||
|
const auto currentChunkOffset = ReadU32(ptr);
|
||||||
|
if (byteCodeSize < currentChunkOffset + sizeof(uint32_t) * 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto currentChunkTag = *reinterpret_cast<const uint32_t*>(byteCode + currentChunkOffset + 0);
|
||||||
|
const auto currentChunkSize = *reinterpret_cast<const uint32_t*>(byteCode + currentChunkOffset + 4);
|
||||||
|
|
||||||
|
if (byteCodeSize < currentChunkOffset + sizeof(uint32_t) * 2 + currentChunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (currentChunkTag == magic)
|
||||||
|
{
|
||||||
|
chunkOffset = currentChunkOffset + 8;
|
||||||
|
chunkSize = currentChunkSize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringFitsInChunk(const char* str, const uint8_t* shaderByteCode, const size_t shaderByteCodeSize)
|
||||||
|
{
|
||||||
|
const auto strLen = strnlen(str, shaderByteCodeSize - (reinterpret_cast<const uint8_t*>(str) - shaderByteCode));
|
||||||
|
return str[strLen] == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundResourceType GetType(const D3D_SHADER_INPUT_TYPE type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case D3D_SIT_CBUFFER:
|
||||||
|
case D3D10_SIT_CBUFFER:
|
||||||
|
return BoundResourceType::CBUFFER;
|
||||||
|
case D3D_SIT_TBUFFER:
|
||||||
|
case D3D10_SIT_TBUFFER:
|
||||||
|
return BoundResourceType::TBUFFER;
|
||||||
|
case D3D_SIT_TEXTURE:
|
||||||
|
case D3D10_SIT_TEXTURE:
|
||||||
|
return BoundResourceType::TEXTURE;
|
||||||
|
case D3D_SIT_SAMPLER:
|
||||||
|
case D3D10_SIT_SAMPLER:
|
||||||
|
return BoundResourceType::SAMPLER;
|
||||||
|
default:
|
||||||
|
return BoundResourceType::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundResourceReturnType GetReturnType(const D3D_RESOURCE_RETURN_TYPE returnType)
|
||||||
|
{
|
||||||
|
switch (returnType)
|
||||||
|
{
|
||||||
|
case D3D_RETURN_TYPE_UNORM:
|
||||||
|
case D3D10_RETURN_TYPE_UNORM:
|
||||||
|
case D3D11_RETURN_TYPE_UNORM:
|
||||||
|
return BoundResourceReturnType::UNORM;
|
||||||
|
case D3D_RETURN_TYPE_SNORM:
|
||||||
|
case D3D10_RETURN_TYPE_SNORM:
|
||||||
|
case D3D11_RETURN_TYPE_SNORM:
|
||||||
|
return BoundResourceReturnType::SNORM;
|
||||||
|
case D3D_RETURN_TYPE_SINT:
|
||||||
|
case D3D10_RETURN_TYPE_SINT:
|
||||||
|
case D3D11_RETURN_TYPE_SINT:
|
||||||
|
return BoundResourceReturnType::SINT;
|
||||||
|
case D3D_RETURN_TYPE_UINT:
|
||||||
|
case D3D10_RETURN_TYPE_UINT:
|
||||||
|
case D3D11_RETURN_TYPE_UINT:
|
||||||
|
return BoundResourceReturnType::UINT;
|
||||||
|
case D3D_RETURN_TYPE_FLOAT:
|
||||||
|
case D3D10_RETURN_TYPE_FLOAT:
|
||||||
|
case D3D11_RETURN_TYPE_FLOAT:
|
||||||
|
return BoundResourceReturnType::FLOAT;
|
||||||
|
case D3D_RETURN_TYPE_MIXED:
|
||||||
|
case D3D10_RETURN_TYPE_MIXED:
|
||||||
|
case D3D11_RETURN_TYPE_MIXED:
|
||||||
|
return BoundResourceReturnType::MIXED;
|
||||||
|
case D3D_RETURN_TYPE_DOUBLE:
|
||||||
|
case D3D11_RETURN_TYPE_DOUBLE:
|
||||||
|
return BoundResourceReturnType::DOUBLE;
|
||||||
|
case D3D_RETURN_TYPE_CONTINUED:
|
||||||
|
case D3D11_RETURN_TYPE_CONTINUED:
|
||||||
|
return BoundResourceReturnType::CONTINUED;
|
||||||
|
default:
|
||||||
|
return BoundResourceReturnType::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundResourceDimension GetDimension(const D3D_SRV_DIMENSION dimension)
|
||||||
|
{
|
||||||
|
switch (dimension)
|
||||||
|
{
|
||||||
|
case D3D_SRV_DIMENSION_BUFFER:
|
||||||
|
case D3D10_SRV_DIMENSION_BUFFER:
|
||||||
|
case D3D10_1_SRV_DIMENSION_BUFFER:
|
||||||
|
case D3D11_SRV_DIMENSION_BUFFER:
|
||||||
|
return BoundResourceDimension::BUFFER;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURE1D:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURE1D:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURE1D:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURE1D:
|
||||||
|
return BoundResourceDimension::TEXTURE_1D;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURE1DARRAY:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURE1DARRAY:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURE1DARRAY:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
|
||||||
|
return BoundResourceDimension::TEXTURE_1D_ARRAY;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURE2D:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURE2D:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURE2D:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURE2D:
|
||||||
|
return BoundResourceDimension::TEXTURE_2D;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURE2DARRAY:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURE2DARRAY:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
|
||||||
|
return BoundResourceDimension::TEXTURE_2D_ARRAY;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURE2DMS:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURE2DMS:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURE2DMS:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURE2DMS:
|
||||||
|
return BoundResourceDimension::TEXTURE_2D_MS;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
||||||
|
return BoundResourceDimension::TEXTURE_2D_MS_ARRAY;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURE3D:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURE3D:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURE3D:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURE3D:
|
||||||
|
return BoundResourceDimension::TEXTURE_3D;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURECUBE:
|
||||||
|
case D3D10_SRV_DIMENSION_TEXTURECUBE:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURECUBE:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURECUBE:
|
||||||
|
return BoundResourceDimension::TEXTURE_CUBE;
|
||||||
|
case D3D_SRV_DIMENSION_TEXTURECUBEARRAY:
|
||||||
|
case D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY:
|
||||||
|
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
|
||||||
|
return BoundResourceDimension::TEXTURE_CUBE_ARRAY;
|
||||||
|
case D3D_SRV_DIMENSION_BUFFEREX:
|
||||||
|
case D3D11_SRV_DIMENSION_BUFFEREX:
|
||||||
|
return BoundResourceDimension::BUFFER_EX;
|
||||||
|
default:
|
||||||
|
return BoundResourceDimension::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopulateBoundResource(BoundResource& boundResource,
|
||||||
|
const FileBoundResource& fileBoundResource,
|
||||||
|
const uint8_t* shaderByteCode,
|
||||||
|
const size_t shaderByteCodeSize,
|
||||||
|
const size_t chunkOffset)
|
||||||
|
{
|
||||||
|
const auto nameString = reinterpret_cast<const char*>(shaderByteCode + chunkOffset + fileBoundResource.nameOffset);
|
||||||
|
|
||||||
|
if (!StringFitsInChunk(nameString, shaderByteCode, shaderByteCodeSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boundResource.m_name = std::string(nameString);
|
||||||
|
boundResource.m_type = GetType(fileBoundResource.type);
|
||||||
|
boundResource.m_return_type = GetReturnType(fileBoundResource.returnType);
|
||||||
|
boundResource.m_dimension = GetDimension(fileBoundResource.dimension);
|
||||||
|
boundResource.m_num_samples = fileBoundResource.numSamples;
|
||||||
|
boundResource.m_bind_point = fileBoundResource.bindPoint;
|
||||||
|
boundResource.m_bind_count = fileBoundResource.bindCount;
|
||||||
|
boundResource.m_flags = fileBoundResource.uFlags;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopulateConstantBufferVariable(ConstantBufferVariable& constantBufferVariable,
|
||||||
|
const FileConstantBufferVariable& fileConstantBufferVariable,
|
||||||
|
const uint8_t* shaderByteCode,
|
||||||
|
const size_t shaderByteCodeSize,
|
||||||
|
const size_t chunkOffset,
|
||||||
|
const size_t chunkSize)
|
||||||
|
{
|
||||||
|
const auto nameString = reinterpret_cast<const char*>(shaderByteCode + chunkOffset + fileConstantBufferVariable.nameOffset);
|
||||||
|
|
||||||
|
if (!StringFitsInChunk(nameString, shaderByteCode, shaderByteCodeSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
constantBufferVariable.m_name = std::string(nameString);
|
||||||
|
constantBufferVariable.m_offset = fileConstantBufferVariable.startOffset;
|
||||||
|
constantBufferVariable.m_size = fileConstantBufferVariable.size;
|
||||||
|
constantBufferVariable.m_flags = fileConstantBufferVariable.flags;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantBufferType GetType(const D3D_CBUFFER_TYPE type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case D3D_CT_CBUFFER:
|
||||||
|
case D3D10_CT_CBUFFER:
|
||||||
|
case D3D11_CT_CBUFFER:
|
||||||
|
return ConstantBufferType::CBUFFER;
|
||||||
|
case D3D_CT_TBUFFER:
|
||||||
|
case D3D10_CT_TBUFFER:
|
||||||
|
case D3D11_CT_TBUFFER:
|
||||||
|
return ConstantBufferType::TBUFFER;
|
||||||
|
case D3D_CT_INTERFACE_POINTERS:
|
||||||
|
case D3D11_CT_INTERFACE_POINTERS:
|
||||||
|
return ConstantBufferType::INTERFACE_POINTERS;
|
||||||
|
case D3D_CT_RESOURCE_BIND_INFO:
|
||||||
|
case D3D11_CT_RESOURCE_BIND_INFO:
|
||||||
|
return ConstantBufferType::RESOURCE_BIND_INFO;
|
||||||
|
default:
|
||||||
|
return ConstantBufferType::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopulateConstantBuffer(ConstantBuffer& constantBuffer,
|
||||||
|
const FileConstantBuffer& fileConstantBuffer,
|
||||||
|
const uint8_t* shaderByteCode,
|
||||||
|
const size_t shaderByteCodeSize,
|
||||||
|
const size_t chunkOffset,
|
||||||
|
const size_t chunkSize,
|
||||||
|
const unsigned targetVersion)
|
||||||
|
{
|
||||||
|
const auto nameString = reinterpret_cast<const char*>(shaderByteCode + chunkOffset + fileConstantBuffer.nameOffset);
|
||||||
|
|
||||||
|
if (!StringFitsInChunk(nameString, shaderByteCode, shaderByteCodeSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
constantBuffer.m_name = std::string(nameString);
|
||||||
|
|
||||||
|
constantBuffer.m_size = fileConstantBuffer.size;
|
||||||
|
constantBuffer.m_flags = fileConstantBuffer.flags;
|
||||||
|
constantBuffer.m_type = GetType(fileConstantBuffer.type);
|
||||||
|
|
||||||
|
if (targetVersion < VERSION_5_0)
|
||||||
|
{
|
||||||
|
const auto* variables = reinterpret_cast<const FileConstantBufferVariable*>(shaderByteCode + chunkOffset + fileConstantBuffer.variableOffset);
|
||||||
|
if (fileConstantBuffer.variableOffset + sizeof(FileConstantBufferVariable) * fileConstantBuffer.variableCount > chunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto variableIndex = 0u; variableIndex < fileConstantBuffer.variableCount; variableIndex++)
|
||||||
|
{
|
||||||
|
const auto& fileVariable = variables[variableIndex];
|
||||||
|
ConstantBufferVariable variable;
|
||||||
|
|
||||||
|
if (!PopulateConstantBufferVariable(variable, fileVariable, shaderByteCode, shaderByteCodeSize, chunkOffset, chunkSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
constantBuffer.m_variables.emplace_back(std::move(variable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto* variables = reinterpret_cast<const FileConstantBufferVariable_5_0*>(shaderByteCode + chunkOffset + fileConstantBuffer.variableOffset);
|
||||||
|
if (fileConstantBuffer.variableOffset + sizeof(FileConstantBufferVariable_5_0) * fileConstantBuffer.variableCount > chunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto variableIndex = 0u; variableIndex < fileConstantBuffer.variableCount; variableIndex++)
|
||||||
|
{
|
||||||
|
const auto& fileVariable = variables[variableIndex];
|
||||||
|
ConstantBufferVariable variable;
|
||||||
|
|
||||||
|
if (!PopulateConstantBufferVariable(variable, fileVariable, shaderByteCode, shaderByteCodeSize, chunkOffset, chunkSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
constantBuffer.m_variables.emplace_back(std::move(variable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopulateShaderInfoFromRdef(ShaderInfo& shaderInfo, const uint8_t* shaderByteCode, const size_t shaderByteCodeSize)
|
||||||
|
{
|
||||||
|
size_t chunkOffset, chunkSize;
|
||||||
|
if (!FindChunk(TAG_RDEF, shaderByteCode, shaderByteCodeSize, chunkOffset, chunkSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sizeof(FileRdefHeader) > chunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto* header = reinterpret_cast<const FileRdefHeader*>(shaderByteCode + chunkOffset);
|
||||||
|
|
||||||
|
const auto targetVersion = header->target & TARGET_VERSION_MASK;
|
||||||
|
const auto creatorString = reinterpret_cast<const char*>(shaderByteCode + chunkOffset + header->creatorOffset);
|
||||||
|
|
||||||
|
if (!StringFitsInChunk(creatorString, shaderByteCode, shaderByteCodeSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
shaderInfo.m_creator = std::string(creatorString);
|
||||||
|
|
||||||
|
if (targetVersion < VERSION_5_1)
|
||||||
|
{
|
||||||
|
const auto* boundResources = reinterpret_cast<const FileBoundResource*>(shaderByteCode + chunkOffset + header->boundResourceOffset);
|
||||||
|
if (header->boundResourceOffset + sizeof(FileBoundResource) * header->boundResourceCount > chunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto boundResourceIndex = 0u; boundResourceIndex < header->boundResourceCount; boundResourceIndex++)
|
||||||
|
{
|
||||||
|
const auto& fileBoundResource = boundResources[boundResourceIndex];
|
||||||
|
BoundResource boundResource;
|
||||||
|
|
||||||
|
PopulateBoundResource(boundResource, fileBoundResource, shaderByteCode, shaderByteCodeSize, chunkOffset);
|
||||||
|
|
||||||
|
shaderInfo.m_bound_resources.emplace_back(std::move(boundResource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto* boundResources = reinterpret_cast<const FileBoundResource_5_1*>(shaderByteCode + chunkOffset + header->boundResourceOffset);
|
||||||
|
if (header->boundResourceOffset + sizeof(FileBoundResource_5_1) * header->boundResourceCount > chunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto boundResourceIndex = 0u; boundResourceIndex < header->boundResourceCount; boundResourceIndex++)
|
||||||
|
{
|
||||||
|
const auto& fileBoundResource = boundResources[boundResourceIndex];
|
||||||
|
BoundResource boundResource;
|
||||||
|
|
||||||
|
if (!PopulateBoundResource(boundResource, fileBoundResource, shaderByteCode, shaderByteCodeSize, chunkOffset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
shaderInfo.m_bound_resources.emplace_back(std::move(boundResource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* constantBuffers = reinterpret_cast<const FileConstantBuffer*>(shaderByteCode + chunkOffset + header->constantBufferOffset);
|
||||||
|
if (header->constantBufferOffset + sizeof(FileConstantBuffer) * header->constantBufferCount > chunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto constantBufferIndex = 0u; constantBufferIndex < header->constantBufferCount; constantBufferIndex++)
|
||||||
|
{
|
||||||
|
const auto& fileConstantBuffer = constantBuffers[constantBufferIndex];
|
||||||
|
ConstantBuffer constantBuffer;
|
||||||
|
|
||||||
|
if (!PopulateConstantBuffer(constantBuffer, fileConstantBuffer, shaderByteCode, shaderByteCodeSize, chunkOffset, chunkSize, targetVersion))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
shaderInfo.m_constant_buffers.emplace_back(std::move(constantBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderType GetShaderType(const FileProgramType programType)
|
||||||
|
{
|
||||||
|
switch (programType)
|
||||||
|
{
|
||||||
|
case D3D10_SB_PIXEL_SHADER:
|
||||||
|
return ShaderType::PIXEL_SHADER;
|
||||||
|
case D3D10_SB_VERTEX_SHADER:
|
||||||
|
return ShaderType::VERTEX_SHADER;
|
||||||
|
case D3D10_SB_GEOMETRY_SHADER:
|
||||||
|
return ShaderType::GEOMETRY_SHADER;
|
||||||
|
case D3D11_SB_HULL_SHADER:
|
||||||
|
return ShaderType::HULL_SHADER;
|
||||||
|
case D3D11_SB_DOMAIN_SHADER:
|
||||||
|
return ShaderType::DOMAIN_SHADER;
|
||||||
|
case D3D11_SB_COMPUTE_SHADER:
|
||||||
|
return ShaderType::COMPUTE_SHADER;
|
||||||
|
default:
|
||||||
|
return ShaderType::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopulateShaderInfoFromShdr(ShaderInfo& shaderInfo, const uint8_t* shaderByteCode, const size_t shaderByteCodeSize)
|
||||||
|
{
|
||||||
|
size_t chunkOffset, chunkSize;
|
||||||
|
if (!FindChunk(TAG_SHDR, shaderByteCode, shaderByteCodeSize, chunkOffset, chunkSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sizeof(FileShaderHeader) > chunkSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto* header = reinterpret_cast<const FileShaderHeader*>(shaderByteCode + chunkOffset);
|
||||||
|
|
||||||
|
shaderInfo.m_version_major = header->versionMajor;
|
||||||
|
shaderInfo.m_version_minor = header->versionMinor;
|
||||||
|
|
||||||
|
shaderInfo.m_type = GetShaderType(header->programType);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopulateShaderInfoFromBytes(ShaderInfo& shaderInfo, const uint8_t* shaderByteCode, const size_t shaderByteCodeSize)
|
||||||
|
{
|
||||||
|
if (!PopulateShaderInfoFromRdef(shaderInfo, shaderByteCode, shaderByteCodeSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!PopulateShaderInfoFromShdr(shaderInfo, shaderByteCode, shaderByteCodeSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace d3d11
|
||||||
|
|
||||||
|
std::unique_ptr<ShaderInfo> ShaderAnalyser::GetShaderInfo(const uint8_t* shader, const size_t shaderSize)
|
||||||
|
{
|
||||||
|
if (shader == nullptr || shaderSize == 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto shaderInfo = std::make_unique<ShaderInfo>();
|
||||||
|
|
||||||
|
if (!PopulateShaderInfoFromBytes(*shaderInfo, shader, shaderSize))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return shaderInfo;
|
||||||
|
}
|
136
src/ObjCommon/Shader/D3D11ShaderAnalyser.h
Normal file
136
src/ObjCommon/Shader/D3D11ShaderAnalyser.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace d3d11
|
||||||
|
{
|
||||||
|
enum class ShaderType
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
PIXEL_SHADER,
|
||||||
|
VERTEX_SHADER,
|
||||||
|
GEOMETRY_SHADER,
|
||||||
|
HULL_SHADER,
|
||||||
|
DOMAIN_SHADER,
|
||||||
|
COMPUTE_SHADER
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstantBufferVariable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConstantBufferVariable();
|
||||||
|
~ConstantBufferVariable() = default;
|
||||||
|
ConstantBufferVariable(const ConstantBufferVariable& other) = default;
|
||||||
|
ConstantBufferVariable(ConstantBufferVariable&& other) noexcept = default;
|
||||||
|
ConstantBufferVariable& operator=(const ConstantBufferVariable& other) = default;
|
||||||
|
ConstantBufferVariable& operator=(ConstantBufferVariable&& other) noexcept = default;
|
||||||
|
|
||||||
|
std::string m_name;
|
||||||
|
unsigned m_offset;
|
||||||
|
unsigned m_size;
|
||||||
|
unsigned m_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ConstantBufferType
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
CBUFFER,
|
||||||
|
TBUFFER,
|
||||||
|
INTERFACE_POINTERS,
|
||||||
|
RESOURCE_BIND_INFO,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstantBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConstantBuffer();
|
||||||
|
~ConstantBuffer() = default;
|
||||||
|
ConstantBuffer(const ConstantBuffer& other) = default;
|
||||||
|
ConstantBuffer(ConstantBuffer&& other) noexcept = default;
|
||||||
|
ConstantBuffer& operator=(const ConstantBuffer& other) = default;
|
||||||
|
ConstantBuffer& operator=(ConstantBuffer&& other) noexcept = default;
|
||||||
|
|
||||||
|
std::string m_name;
|
||||||
|
unsigned m_size;
|
||||||
|
unsigned m_flags;
|
||||||
|
ConstantBufferType m_type;
|
||||||
|
std::vector<ConstantBufferVariable> m_variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BoundResourceType
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
CBUFFER,
|
||||||
|
TBUFFER,
|
||||||
|
TEXTURE,
|
||||||
|
SAMPLER
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BoundResourceReturnType
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
UNORM,
|
||||||
|
SNORM,
|
||||||
|
SINT,
|
||||||
|
UINT,
|
||||||
|
FLOAT,
|
||||||
|
MIXED,
|
||||||
|
DOUBLE,
|
||||||
|
CONTINUED,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BoundResourceDimension
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
BUFFER,
|
||||||
|
TEXTURE_1D,
|
||||||
|
TEXTURE_1D_ARRAY,
|
||||||
|
TEXTURE_2D,
|
||||||
|
TEXTURE_2D_ARRAY,
|
||||||
|
TEXTURE_2D_MS,
|
||||||
|
TEXTURE_2D_MS_ARRAY,
|
||||||
|
TEXTURE_3D,
|
||||||
|
TEXTURE_CUBE,
|
||||||
|
TEXTURE_CUBE_ARRAY,
|
||||||
|
BUFFER_EX,
|
||||||
|
};
|
||||||
|
|
||||||
|
class BoundResource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BoundResource();
|
||||||
|
~BoundResource() = default;
|
||||||
|
BoundResource(const BoundResource& other) = default;
|
||||||
|
BoundResource(BoundResource&& other) noexcept = default;
|
||||||
|
BoundResource& operator=(const BoundResource& other) = default;
|
||||||
|
BoundResource& operator=(BoundResource&& other) noexcept = default;
|
||||||
|
|
||||||
|
std::string m_name;
|
||||||
|
BoundResourceType m_type;
|
||||||
|
BoundResourceReturnType m_return_type;
|
||||||
|
BoundResourceDimension m_dimension;
|
||||||
|
unsigned m_num_samples;
|
||||||
|
unsigned m_bind_point;
|
||||||
|
unsigned m_bind_count;
|
||||||
|
unsigned m_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShaderType m_type = ShaderType::UNKNOWN;
|
||||||
|
unsigned m_version_major = 0;
|
||||||
|
unsigned m_version_minor = 0;
|
||||||
|
std::string m_creator;
|
||||||
|
std::vector<ConstantBuffer> m_constant_buffers;
|
||||||
|
std::vector<BoundResource> m_bound_resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderAnalyser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<ShaderInfo> GetShaderInfo(const uint8_t* shader, size_t shaderSize);
|
||||||
|
};
|
||||||
|
} // namespace d3d11
|
@ -1,12 +1,17 @@
|
|||||||
#include "AssetDumperMaterial.h"
|
#include "AssetDumperMaterial.h"
|
||||||
|
|
||||||
#include "Game/T6/CommonT6.h"
|
#include "Game/T6/CommonT6.h"
|
||||||
|
#include "Game/T6/GameAssetPoolT6.h"
|
||||||
|
#include "Game/T6/GameT6.h"
|
||||||
#include "Game/T6/MaterialConstantsT6.h"
|
#include "Game/T6/MaterialConstantsT6.h"
|
||||||
#include "Game/T6/TechsetConstantsT6.h"
|
#include "Game/T6/TechsetConstantsT6.h"
|
||||||
|
#include "ObjWriting.h"
|
||||||
|
#include "Shader/D3D11ShaderAnalyser.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
using namespace T6;
|
using namespace T6;
|
||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
@ -18,17 +23,647 @@ namespace T6::material
|
|||||||
Common::R_HashString(strValue, 0), strValue \
|
Common::R_HashString(strValue, 0), strValue \
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<unsigned, std::string> knownHashes{
|
static constexpr const char* SAMPLER_STR = "Sampler";
|
||||||
KNOWN_HASH("colorMap"),
|
static constexpr const char* GLOBALS_CBUFFER_NAME = "$Globals";
|
||||||
KNOWN_HASH("normalMap"),
|
static constexpr const char* PER_OBJECT_CONSTS_CBUFFER_NAME = "PerObjectConsts";
|
||||||
KNOWN_HASH("specularMap"),
|
|
||||||
|
const char* KNOWN_CONSTANT_NAMES[]{
|
||||||
|
"AngularVelocityScale",
|
||||||
|
"AnimSpeed",
|
||||||
|
"Background",
|
||||||
|
"BackgroundColor",
|
||||||
|
"BackgroundNoise",
|
||||||
|
"BakedLightingIntensity",
|
||||||
|
"BloodBrightness",
|
||||||
|
"BloodIntensity",
|
||||||
|
"BlurAmount",
|
||||||
|
"CapWidth",
|
||||||
|
"Char_Size",
|
||||||
|
"Char_Width",
|
||||||
|
"Coarseness",
|
||||||
|
"Color",
|
||||||
|
"ColorAmount",
|
||||||
|
"ColorBias",
|
||||||
|
"Color_Map_Noise",
|
||||||
|
"Color_Map_Scale",
|
||||||
|
"Color_Map_Size_Scale",
|
||||||
|
"DDXScale",
|
||||||
|
"DDYScale",
|
||||||
|
"DarkenAmount",
|
||||||
|
"DarkenPower",
|
||||||
|
"Detail_Amount",
|
||||||
|
"Detail_Normal_Tile",
|
||||||
|
"Diffuse_Normal_Height_Facing",
|
||||||
|
"Dimensions",
|
||||||
|
"DispersionAmount",
|
||||||
|
"Dolly",
|
||||||
|
"EdgeColor",
|
||||||
|
"EdgeHarshness",
|
||||||
|
"EdgeIntensity",
|
||||||
|
"EdgeMaxDist",
|
||||||
|
"EdgeMinDist",
|
||||||
|
"EdgeSize",
|
||||||
|
"Edge_Color_Multiplier",
|
||||||
|
"Emissive_Amount",
|
||||||
|
"EnemiesColor",
|
||||||
|
"Exposure",
|
||||||
|
"FPS",
|
||||||
|
"Fade_Distance",
|
||||||
|
"Fill_Direction",
|
||||||
|
"Fill_Direction2",
|
||||||
|
"FirstFrame",
|
||||||
|
"FlareIntensity",
|
||||||
|
"FlareScale",
|
||||||
|
"FlattenEdges",
|
||||||
|
"Flicker_Max",
|
||||||
|
"Flicker_Min",
|
||||||
|
"Flicker_Seed",
|
||||||
|
"Flicker_Speed",
|
||||||
|
"Font_Color",
|
||||||
|
"Gamma",
|
||||||
|
"GlossAmount",
|
||||||
|
"Gloss_Amount",
|
||||||
|
"Glow_Alt_Color",
|
||||||
|
"Glow_Color",
|
||||||
|
"Glow_Falloff",
|
||||||
|
"GradientColor",
|
||||||
|
"GradientMax",
|
||||||
|
"GradientMin",
|
||||||
|
"Grain_Amount",
|
||||||
|
"Grain_Color",
|
||||||
|
"Grid",
|
||||||
|
"Hardness",
|
||||||
|
"Heart_Rate_Offset",
|
||||||
|
"Heart_Rate_Scale",
|
||||||
|
"Highlight_1_Brightness",
|
||||||
|
"Highlight_1_Sharpness",
|
||||||
|
"Highlight_2_Brightness",
|
||||||
|
"Highlight_2_Sharpness",
|
||||||
|
"Highlight_2_Size",
|
||||||
|
"Hightlight_1_Size",
|
||||||
|
"Holo_Scale",
|
||||||
|
"LastFrame",
|
||||||
|
"Layer1Alpha",
|
||||||
|
"Layer1Depth",
|
||||||
|
"Layer1Offset",
|
||||||
|
"Layer1OffsetBobbleDelay",
|
||||||
|
"Layer1OffsetBobbleSpeedAndSize",
|
||||||
|
"Layer1Origin",
|
||||||
|
"Layer1Rotation",
|
||||||
|
"Layer1Scale",
|
||||||
|
"Layer1ScaleBobbleDelay",
|
||||||
|
"Layer1ScaleBobbleSpeedAndSize",
|
||||||
|
"Layer1Scroll",
|
||||||
|
"Layer2Alpha",
|
||||||
|
"Layer2Depth",
|
||||||
|
"Layer2Offset",
|
||||||
|
"Layer2OffsetBobbleDelay",
|
||||||
|
"Layer2OffsetBobbleSpeedAndSize",
|
||||||
|
"Layer2Origin",
|
||||||
|
"Layer2Rotation",
|
||||||
|
"Layer2Scale",
|
||||||
|
"Layer2ScaleBobbleDelay",
|
||||||
|
"Layer2ScaleBobbleSpeedAndSize",
|
||||||
|
"Layer2Scroll",
|
||||||
|
"Layer3Alpha",
|
||||||
|
"Layer3Depth",
|
||||||
|
"Layer3Offset",
|
||||||
|
"Layer3Origin",
|
||||||
|
"Layer3Rotation",
|
||||||
|
"Layer3Scale",
|
||||||
|
"Layer3Scroll",
|
||||||
|
"Layer4Alpha",
|
||||||
|
"Layer4Depth",
|
||||||
|
"Layer4Offset",
|
||||||
|
"Layer4Origin",
|
||||||
|
"Layer4Rotation",
|
||||||
|
"Layer4Scale",
|
||||||
|
"Layer4Scroll",
|
||||||
|
"LineColor",
|
||||||
|
"LineNoise",
|
||||||
|
"LineWidth",
|
||||||
|
"MaxDepth",
|
||||||
|
"MaxFlickerColor",
|
||||||
|
"MaxPulseDepth",
|
||||||
|
"MaxResolution",
|
||||||
|
"Max_Color",
|
||||||
|
"Maximum_Distance",
|
||||||
|
"Midlayer_Depth",
|
||||||
|
"MinDepth",
|
||||||
|
"MinFlickerColor",
|
||||||
|
"MinResolution",
|
||||||
|
"MinStatic",
|
||||||
|
"MinVelocityFraction",
|
||||||
|
"Min_Color",
|
||||||
|
"Min_Player_Intensity",
|
||||||
|
"MomentumColor",
|
||||||
|
"NegativeColor",
|
||||||
|
"NoisePower",
|
||||||
|
"Noise_Scale",
|
||||||
|
"NormalHeightMultiplier",
|
||||||
|
"Normal_Detail_Height",
|
||||||
|
"Normal_Detail_Scale",
|
||||||
|
"Normal_Map_Size_Scale",
|
||||||
|
"Normal_Variance_Scale",
|
||||||
|
"NumFrames",
|
||||||
|
"Outline_Lookup_Scale",
|
||||||
|
"OverallAmount",
|
||||||
|
"OverallBrightness",
|
||||||
|
"Overlay_Color",
|
||||||
|
"P1",
|
||||||
|
"P2",
|
||||||
|
"Padding",
|
||||||
|
"Player_Color_Multiplier",
|
||||||
|
"Player_Lookup_Scale",
|
||||||
|
"PositiveColor",
|
||||||
|
"Power",
|
||||||
|
"PulseColor",
|
||||||
|
"PulseInterval",
|
||||||
|
"PulseTime",
|
||||||
|
"Pulse_Color_Multiplier",
|
||||||
|
"Pulse_Lookup_Scale",
|
||||||
|
"Radius",
|
||||||
|
"ReflectionAmount",
|
||||||
|
"Reflection_Amount",
|
||||||
|
"Reflection_Blur",
|
||||||
|
"Reticle_Alt_Color",
|
||||||
|
"Reticle_Color",
|
||||||
|
"Row_Chars_",
|
||||||
|
"Scale",
|
||||||
|
"ScanlineColor",
|
||||||
|
"ScanlineIntensity",
|
||||||
|
"ScanlineOffset",
|
||||||
|
"ScanlinePower",
|
||||||
|
"ScanlineSpeed",
|
||||||
|
"ScatterAmount",
|
||||||
|
"ScatterSize",
|
||||||
|
"SceneNoise",
|
||||||
|
"SparkleBrightness",
|
||||||
|
"SparkleDensity",
|
||||||
|
"SparklePower",
|
||||||
|
"SparkleProbeAmount",
|
||||||
|
"SparkleScale",
|
||||||
|
"SparkleSpecAmount",
|
||||||
|
"SparkleWash",
|
||||||
|
"SpecGloss_Map_Size_Scale",
|
||||||
|
"SpecularAmount",
|
||||||
|
"SpecularColor",
|
||||||
|
"Specular_Amount",
|
||||||
|
"Specular_Decay_Threshold",
|
||||||
|
"Speed",
|
||||||
|
"StaticAmount",
|
||||||
|
"StaticLookupSpeed",
|
||||||
|
"StaticLookupX",
|
||||||
|
"StaticScale",
|
||||||
|
"Static_Size",
|
||||||
|
"Static_amount",
|
||||||
|
"TearLookupMaxX",
|
||||||
|
"TearLookupMinX",
|
||||||
|
"TearLookupSpeed",
|
||||||
|
"TearMultiplier",
|
||||||
|
"TearPower",
|
||||||
|
"Thickness",
|
||||||
|
"TickMarkColorAndHarshness",
|
||||||
|
"Tint",
|
||||||
|
"VelocityScale",
|
||||||
|
"VignetteMultiplier",
|
||||||
|
"VignettePower",
|
||||||
|
"WarpAmount",
|
||||||
|
"WarpHeight",
|
||||||
|
"WarpScale",
|
||||||
|
"WarpSpeed",
|
||||||
|
"WashOut",
|
||||||
|
"WashoutMultiply",
|
||||||
|
"WaterDirection",
|
||||||
|
"WaterHeight",
|
||||||
|
"WaterRefraction",
|
||||||
|
"WaterScale1",
|
||||||
|
"WaterScale2",
|
||||||
|
"WaterSpeed1",
|
||||||
|
"WaterSpeed2",
|
||||||
|
"Zoom",
|
||||||
|
"alphaDissolveParms",
|
||||||
|
"alphaRevealParms",
|
||||||
|
"alphaRevealParms1",
|
||||||
|
"alphaRevealParms2",
|
||||||
|
"alphaRevealParms3",
|
||||||
|
"alphaRevealParms4",
|
||||||
|
"clipSpaceLookupOffset",
|
||||||
|
"clipSpaceLookupScale",
|
||||||
|
"cloudsFeather",
|
||||||
|
"cloudsHeights",
|
||||||
|
"cloudsUVMad1",
|
||||||
|
"cloudsUVMad2",
|
||||||
|
"cloudsUVMul1",
|
||||||
|
"cloudsUVMul2",
|
||||||
|
"codeMeshArg",
|
||||||
|
"colorDetailScale",
|
||||||
|
"colorObjMax",
|
||||||
|
"colorObjMaxBaseBlend",
|
||||||
|
"colorObjMin",
|
||||||
|
"colorObjMinBaseBlend",
|
||||||
|
"colorTint",
|
||||||
|
"debugBumpmap",
|
||||||
|
"debugPerformance",
|
||||||
|
"detailScale",
|
||||||
|
"detailScale1",
|
||||||
|
"detailScale2",
|
||||||
|
"detailScale3",
|
||||||
|
"detailScale4",
|
||||||
|
"distortionScale",
|
||||||
|
"dofEquationScene",
|
||||||
|
"dofEquationViewModelAndFarBlur",
|
||||||
|
"dofLerpBias",
|
||||||
|
"dofLerpDownBias",
|
||||||
|
"dofLerpDownScale",
|
||||||
|
"dofLerpScale",
|
||||||
|
"dofLerpUpBias",
|
||||||
|
"dofLerpUpScale",
|
||||||
|
"dofRowDelta",
|
||||||
|
"eyeOffsetParms",
|
||||||
|
"falloffBeginColor",
|
||||||
|
"falloffEndColor",
|
||||||
|
"falloffParms",
|
||||||
|
"featherParms",
|
||||||
|
"flagParams",
|
||||||
|
"framebufferRead",
|
||||||
|
"gameTime",
|
||||||
|
"hdrAmount",
|
||||||
|
"inverseTransposeWorldMatrix",
|
||||||
|
"inverseTransposeWorldViewMatrix",
|
||||||
|
"inverseWorldMatrix",
|
||||||
|
"inverseWorldViewMatrix",
|
||||||
|
"motionblurDirectionAndMagnitude",
|
||||||
|
"occlusionAmount",
|
||||||
|
"occlusionAmount1",
|
||||||
|
"occlusionAmount2",
|
||||||
|
"occlusionAmount3",
|
||||||
|
"occlusionAmount4",
|
||||||
|
"particleCloudColor",
|
||||||
|
"particleCloudMatrix",
|
||||||
|
"particleCloudVelWorld",
|
||||||
|
"resizeParams1",
|
||||||
|
"resizeParams2",
|
||||||
|
"scaleRGB",
|
||||||
|
"scriptVector0",
|
||||||
|
"scriptVector1",
|
||||||
|
"scriptVector2",
|
||||||
|
"scriptVector3",
|
||||||
|
"scriptVector4",
|
||||||
|
"scriptVector5",
|
||||||
|
"scriptVector6",
|
||||||
|
"scriptVector7",
|
||||||
|
"skyBoxCloudWeights",
|
||||||
|
"skyBoxRotationSize",
|
||||||
|
"skyColorParms",
|
||||||
|
"spotLightWeight",
|
||||||
|
"treeCanopyLightingParms",
|
||||||
|
"treeCanopyScatterColor",
|
||||||
|
"treeCanopySwayParms",
|
||||||
|
"ui3dUVSetup0",
|
||||||
|
"ui3dUVSetup1",
|
||||||
|
"ui3dUVSetup2",
|
||||||
|
"ui3dUVSetup3",
|
||||||
|
"ui3dUVSetup4",
|
||||||
|
"ui3dUVSetup5",
|
||||||
|
"uvAnimParms",
|
||||||
|
"uvScroll",
|
||||||
|
"viewMatrix",
|
||||||
|
"weaponParam0",
|
||||||
|
"weaponParam1",
|
||||||
|
"weaponParam2",
|
||||||
|
"weaponParam3",
|
||||||
|
"weaponParam4",
|
||||||
|
"weaponParam5",
|
||||||
|
"weaponParam6",
|
||||||
|
"weaponParam7",
|
||||||
|
"weaponParam8",
|
||||||
|
"weaponParam9",
|
||||||
|
"worldViewMatrix",
|
||||||
|
"worldViewProjectionMatrix",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* KNOWN_TEXTURE_DEF_NAMES[]{
|
||||||
|
"AddMap",
|
||||||
|
"Blip_Mask",
|
||||||
|
"BlockNoise",
|
||||||
|
"CS_Z_buffer",
|
||||||
|
"Camo_Detail_Map",
|
||||||
|
"Color_Map",
|
||||||
|
"CompassMap",
|
||||||
|
"Detail_Map",
|
||||||
|
"Diffuse",
|
||||||
|
"Diffuse_Map",
|
||||||
|
"DpadTexture",
|
||||||
|
"FontTextutre",
|
||||||
|
"Grain_Map",
|
||||||
|
"GridTexture",
|
||||||
|
"GrimeMap",
|
||||||
|
"Heart_Rate_Image",
|
||||||
|
"Hologram_Diffuse",
|
||||||
|
"Image",
|
||||||
|
"Layer1Map",
|
||||||
|
"Layer2Map",
|
||||||
|
"Layer3Map",
|
||||||
|
"Layer4Map",
|
||||||
|
"Lookup",
|
||||||
|
"Lookup2",
|
||||||
|
"LookupMap",
|
||||||
|
"Mask",
|
||||||
|
"Noise",
|
||||||
|
"Noise_Texture",
|
||||||
|
"NormalDetailMap",
|
||||||
|
"Normal_Detail_Map",
|
||||||
|
"Normal_Map",
|
||||||
|
"Overlay_Map",
|
||||||
|
"Reflection_Mask",
|
||||||
|
"Reveal_Map",
|
||||||
|
"Rim_Color_Mask",
|
||||||
|
"Rim_Specular_Mask",
|
||||||
|
"Rim_Occlusion_Mask",
|
||||||
|
"Scanline",
|
||||||
|
"SparkleMap",
|
||||||
|
"SpecularAndGloss",
|
||||||
|
"SpecularAndGloss2",
|
||||||
|
"Specular_Color_Map",
|
||||||
|
"Specular_Gloss_Map",
|
||||||
|
"Specular_Map",
|
||||||
|
"SpotShadowSamplerState",
|
||||||
|
"SpotShadowState",
|
||||||
|
"SpriteMap",
|
||||||
|
"Static",
|
||||||
|
"StaticMap",
|
||||||
|
"Static_Noise_Map",
|
||||||
|
"SunShadowSamplerState",
|
||||||
|
"SunShadowState",
|
||||||
|
"Surface_Normal_Map",
|
||||||
|
"ThermalMapMask",
|
||||||
|
"Thermal_Gradient",
|
||||||
|
"Thermal_Map",
|
||||||
|
"TickMarkMaterial",
|
||||||
|
"Tile",
|
||||||
|
"WarpMap",
|
||||||
|
"WaterNormalMap",
|
||||||
|
"Weapon_Normal_Map",
|
||||||
|
"Weapon_Specular_Map",
|
||||||
|
"Wireframe",
|
||||||
|
"ZBuffer_Map",
|
||||||
|
"attenuation",
|
||||||
|
"attenuationSampler",
|
||||||
|
"baseLut2D",
|
||||||
|
"baseLut2DSampler",
|
||||||
|
"cinematicA",
|
||||||
|
"cinematicASampler",
|
||||||
|
"cinematicCb",
|
||||||
|
"cinematicCbSampler",
|
||||||
|
"cinematicCr",
|
||||||
|
"cinematicCrSampler",
|
||||||
|
"cinematicY",
|
||||||
|
"cinematicYSampler",
|
||||||
|
"codeTexture0",
|
||||||
|
"codeTexture1",
|
||||||
|
"codeTexture2",
|
||||||
|
"color",
|
||||||
|
"colorDetailMap",
|
||||||
|
"colorDetailMapSampler",
|
||||||
|
"colorMap",
|
||||||
|
"colorMap1",
|
||||||
|
"colorMap2",
|
||||||
|
"colorMap2D",
|
||||||
|
"colorMapPostSun",
|
||||||
|
"colorMapPostSunSampler",
|
||||||
|
"colorMapSampler",
|
||||||
|
"colorMapSampler1",
|
||||||
|
"colorMapSampler2",
|
||||||
|
"colorSampler",
|
||||||
|
"detailMap",
|
||||||
|
"detailMapSampler",
|
||||||
|
"dlightAttenuation",
|
||||||
|
"dlightAttenuationSampler",
|
||||||
|
"floatZ",
|
||||||
|
"floatZSampler",
|
||||||
|
"imageSampler",
|
||||||
|
"lightmapSamplerSecondary",
|
||||||
|
"lightmapSecondary",
|
||||||
|
"lut2D",
|
||||||
|
"lut2DSampler",
|
||||||
|
"lut3D",
|
||||||
|
"lut3DSampler",
|
||||||
|
"missileCam",
|
||||||
|
"missileCamSampler",
|
||||||
|
"modelLighting",
|
||||||
|
"modelLightingSampler",
|
||||||
|
"normalMap",
|
||||||
|
"normalMap1",
|
||||||
|
"normalMap2",
|
||||||
|
"normalMapSampler",
|
||||||
|
"normalMapSampler1",
|
||||||
|
"normalMapSampler2",
|
||||||
|
"occlusionMap",
|
||||||
|
"occlusionMapSampler",
|
||||||
|
"occMap",
|
||||||
|
"occMapSampler",
|
||||||
|
"outdoorMap",
|
||||||
|
"outdoorMapSampler",
|
||||||
|
"radiantDiffuseMap",
|
||||||
|
"rawFloatZ",
|
||||||
|
"rawFloatZSampler",
|
||||||
|
"reflectionProbe",
|
||||||
|
"reflectionProbeSampler",
|
||||||
|
"shadowmapSamplerSpot",
|
||||||
|
"shadowmapSamplerSun",
|
||||||
|
"shadowmapSpot",
|
||||||
|
"shadowmapSun",
|
||||||
|
"sonarColor",
|
||||||
|
"sonarColorSampler",
|
||||||
|
"sonarDepth",
|
||||||
|
"sonarDepthSampler",
|
||||||
|
"source",
|
||||||
|
"specularMap",
|
||||||
|
"specularMap1",
|
||||||
|
"specularMap2",
|
||||||
|
"specularMapSampler",
|
||||||
|
"specularMapSampler1",
|
||||||
|
"specularMapSampler2",
|
||||||
|
"stencil",
|
||||||
|
"stencilSampler",
|
||||||
|
"ui3d",
|
||||||
|
"ui3dSampler",
|
||||||
|
};
|
||||||
|
|
||||||
|
class MaterialConstantZoneState final : public IZoneAssetDumperState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void ExtractNamesFromZone()
|
||||||
|
{
|
||||||
|
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<const GameAssetPoolT6*>(zone->m_pools.get());
|
||||||
|
if (!t6AssetPools)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const auto* techniqueSetInfo : *t6AssetPools->m_technique_set)
|
||||||
|
{
|
||||||
|
const auto* techniqueSet = techniqueSetInfo->Asset();
|
||||||
|
|
||||||
|
for (const auto* technique : techniqueSet->techniques)
|
||||||
|
{
|
||||||
|
if (technique)
|
||||||
|
ExtractNamesFromTechnique(technique);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ExtractNamesFromTechnique(const MaterialTechnique* technique)
|
||||||
|
{
|
||||||
|
const auto existingTechnique = m_dumped_techniques.find(technique);
|
||||||
|
if (existingTechnique != m_dumped_techniques.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_dumped_techniques.emplace(technique);
|
||||||
|
|
||||||
|
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
|
||||||
|
{
|
||||||
|
const auto& pass = technique->passArray[passIndex];
|
||||||
|
|
||||||
|
if (pass.vertexShader && pass.vertexShader->prog.loadDef.program)
|
||||||
|
ExtractNamesFromShader(pass.vertexShader->prog.loadDef.program, pass.vertexShader->prog.loadDef.programSize);
|
||||||
|
|
||||||
|
if (pass.pixelShader && pass.pixelShader->prog.loadDef.program)
|
||||||
|
ExtractNamesFromShader(pass.pixelShader->prog.loadDef.program, pass.pixelShader->prog.loadDef.programSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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::find_if(shaderInfo->m_constant_buffers.cbegin(),
|
||||||
|
shaderInfo->m_constant_buffers.cend(),
|
||||||
|
[](const d3d11::ConstantBuffer& constantBuffer)
|
||||||
|
{
|
||||||
|
return constantBuffer.m_name == GLOBALS_CBUFFER_NAME;
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto perObjectConsts = std::find_if(shaderInfo->m_constant_buffers.cbegin(),
|
||||||
|
shaderInfo->m_constant_buffers.cend(),
|
||||||
|
[](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 AddStaticKnownNames()
|
||||||
|
{
|
||||||
|
for (const auto* knownConstantName : KNOWN_CONSTANT_NAMES)
|
||||||
|
AddConstantName(knownConstantName);
|
||||||
|
for (const auto* knownTextureDefName : KNOWN_TEXTURE_DEF_NAMES)
|
||||||
|
AddTextureDefName(knownTextureDefName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddConstantName(std::string constantName)
|
||||||
|
{
|
||||||
|
const auto hash = Common::R_HashString(constantName.c_str(), 0);
|
||||||
|
if (m_constant_names_from_shaders.find(hash) != m_constant_names_from_shaders.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_constant_names_from_shaders.emplace(hash, std::move(constantName));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddTextureDefName(std::string textureDefName)
|
||||||
|
{
|
||||||
|
const auto hash = Common::R_HashString(textureDefName.c_str(), 0);
|
||||||
|
if (m_texture_def_names_from_shaders.find(hash) != m_texture_def_names_from_shaders.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_texture_def_names_from_shaders.emplace(hash, std::move(textureDefName));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonDumper
|
class JsonDumper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit JsonDumper(std::ostream& stream)
|
explicit JsonDumper(AssetDumpingContext& context, std::ostream& stream)
|
||||||
: m_stream(stream)
|
: m_stream(stream),
|
||||||
|
m_material_constants(*context.GetZoneAssetDumperState<MaterialConstantZoneState>())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +696,9 @@ namespace T6::material
|
|||||||
j[key] = nullptr;
|
j[key] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MaterialToJson(json& jRoot, const Material* material)
|
void MaterialToJson(json& jRoot, const Material* material) const
|
||||||
{
|
{
|
||||||
|
|
||||||
MaterialInfoToJson(jRoot, material);
|
MaterialInfoToJson(jRoot, material);
|
||||||
StateBitsEntryToJson(jRoot, material);
|
StateBitsEntryToJson(jRoot, material);
|
||||||
jRoot["stateFlags"] = material->stateFlags;
|
jRoot["stateFlags"] = material->stateFlags;
|
||||||
@ -128,7 +764,7 @@ namespace T6::material
|
|||||||
jRoot["techniqueSet"] = nullptr;
|
jRoot["techniqueSet"] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TextureTableToJson(json& jRoot, const Material* material)
|
void TextureTableToJson(json& jRoot, const Material* material) const
|
||||||
{
|
{
|
||||||
json jTextures = json::array();
|
json jTextures = json::array();
|
||||||
if (material->textureTable)
|
if (material->textureTable)
|
||||||
@ -143,19 +779,19 @@ namespace T6::material
|
|||||||
jRoot["textures"] = std::move(jTextures);
|
jRoot["textures"] = std::move(jTextures);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TextureDefToJson(json& jTexture, const MaterialTextureDef* textureDef)
|
void TextureDefToJson(json& jTexture, const MaterialTextureDef* textureDef) const
|
||||||
{
|
{
|
||||||
const auto knownHash = knownHashes.find(textureDef->nameHash);
|
std::string textureDefName;
|
||||||
if (knownHash == knownHashes.end())
|
if (m_material_constants.GetTextureDefName(textureDef->nameHash, textureDefName))
|
||||||
|
{
|
||||||
|
jTexture["name"] = textureDefName;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
jTexture["nameHash"] = textureDef->nameHash;
|
jTexture["nameHash"] = textureDef->nameHash;
|
||||||
jTexture["nameStart"] = std::string(1u, textureDef->nameStart);
|
jTexture["nameStart"] = std::string(1u, textureDef->nameStart);
|
||||||
jTexture["nameEnd"] = std::string(1u, textureDef->nameEnd);
|
jTexture["nameEnd"] = std::string(1u, textureDef->nameEnd);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
jTexture["name"] = knownHash->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonEnumEntry(jTexture, "semantic", textureDef->semantic, textureSemanticNames);
|
JsonEnumEntry(jTexture, "semantic", textureDef->semantic, textureSemanticNames);
|
||||||
jTexture["isMatureContent"] = textureDef->isMatureContent;
|
jTexture["isMatureContent"] = textureDef->isMatureContent;
|
||||||
@ -179,7 +815,7 @@ namespace T6::material
|
|||||||
jSamplerState["clampW"] = samplerState.clampW ? true : false;
|
jSamplerState["clampW"] = samplerState.clampW ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConstantTableToJson(json& jRoot, const Material* material)
|
void ConstantTableToJson(json& jRoot, const Material* material) const
|
||||||
{
|
{
|
||||||
json jConstants = json::array();
|
json jConstants = json::array();
|
||||||
if (material->constantTable)
|
if (material->constantTable)
|
||||||
@ -194,26 +830,31 @@ namespace T6::material
|
|||||||
jRoot["constants"] = std::move(jConstants);
|
jRoot["constants"] = std::move(jConstants);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConstantDefToJson(json& jConstant, const MaterialConstantDef* textureDef)
|
void ConstantDefToJson(json& jConstant, const MaterialConstantDef* constantDef) const
|
||||||
{
|
{
|
||||||
const auto fragmentLength = strnlen(textureDef->name, std::extent_v<decltype(MaterialConstantDef::name)>);
|
const auto fragmentLength = strnlen(constantDef->name, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
const std::string nameFragment(textureDef->name, fragmentLength);
|
const std::string nameFragment(constantDef->name, fragmentLength);
|
||||||
|
std::string knownConstantName;
|
||||||
|
|
||||||
if (fragmentLength < std::extent_v<decltype(MaterialConstantDef::name)> || Common::R_HashString(nameFragment.c_str(), 0) == textureDef->nameHash)
|
if (fragmentLength < std::extent_v<decltype(MaterialConstantDef::name)> || Common::R_HashString(nameFragment.c_str(), 0) == constantDef->nameHash)
|
||||||
{
|
{
|
||||||
jConstant["name"] = nameFragment;
|
jConstant["name"] = nameFragment;
|
||||||
}
|
}
|
||||||
|
else if (m_material_constants.GetConstantName(constantDef->nameHash, knownConstantName))
|
||||||
|
{
|
||||||
|
jConstant["name"] = knownConstantName;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
jConstant["nameHash"] = textureDef->nameHash;
|
jConstant["nameHash"] = constantDef->nameHash;
|
||||||
jConstant["nameFragment"] = nameFragment;
|
jConstant["nameFragment"] = nameFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
json jLiteral;
|
json jLiteral;
|
||||||
jLiteral.push_back(textureDef->literal.v[0]);
|
jLiteral.push_back(constantDef->literal.v[0]);
|
||||||
jLiteral.push_back(textureDef->literal.v[1]);
|
jLiteral.push_back(constantDef->literal.v[1]);
|
||||||
jLiteral.push_back(textureDef->literal.v[2]);
|
jLiteral.push_back(constantDef->literal.v[2]);
|
||||||
jLiteral.push_back(textureDef->literal.v[3]);
|
jLiteral.push_back(constantDef->literal.v[3]);
|
||||||
jConstant["literal"] = std::move(jLiteral);
|
jConstant["literal"] = std::move(jLiteral);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,6 +965,7 @@ namespace T6::material
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& m_stream;
|
std::ostream& m_stream;
|
||||||
|
const MaterialConstantZoneState& m_material_constants;
|
||||||
};
|
};
|
||||||
} // namespace T6::material
|
} // namespace T6::material
|
||||||
|
|
||||||
@ -357,6 +999,14 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Mat
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const material::JsonDumper dumper(*assetFile);
|
const material::JsonDumper dumper(context, *assetFile);
|
||||||
dumper.Dump(asset->Asset());
|
dumper.Dump(asset->Asset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool)
|
||||||
|
{
|
||||||
|
auto* materialConstantState = context.GetZoneAssetDumperState<material::MaterialConstantZoneState>();
|
||||||
|
materialConstantState->ExtractNamesFromZone();
|
||||||
|
|
||||||
|
AbstractAssetDumper<Material>::DumpPool(context, pool);
|
||||||
|
}
|
||||||
|
@ -14,5 +14,8 @@ namespace T6
|
|||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<Material>* asset) override;
|
bool ShouldDump(XAssetInfo<Material>* asset) override;
|
||||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset) override;
|
void DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void DumpPool(AssetDumpingContext& context, AssetPool<Material>* pool) override;
|
||||||
};
|
};
|
||||||
} // namespace T6
|
} // namespace T6
|
||||||
|
Loading…
x
Reference in New Issue
Block a user