mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-03-05 12:33:02 +00:00
chore: extract more information from d3d11 shaders
This commit is contained in:
@@ -29,7 +29,12 @@ namespace d3d11
|
||||
ConstantBufferVariable::ConstantBufferVariable()
|
||||
: m_offset(0u),
|
||||
m_size(0u),
|
||||
m_flags(0u)
|
||||
m_flags(0u),
|
||||
m_is_used(false),
|
||||
m_variable_class(VariableClass::UNKNOWN),
|
||||
m_element_count(0),
|
||||
m_row_count(0),
|
||||
m_column_count(0)
|
||||
{
|
||||
}
|
||||
} // namespace d3d11
|
||||
@@ -39,9 +44,6 @@ namespace
|
||||
constexpr auto TAG_RDEF = FileUtils::MakeMagic32('R', 'D', 'E', 'F');
|
||||
constexpr auto TAG_SHDR = FileUtils::MakeMagic32('S', 'H', 'D', 'R');
|
||||
|
||||
constexpr auto VERSION_5_0 = 0x500;
|
||||
constexpr auto VERSION_5_1 = 0x501;
|
||||
constexpr auto TARGET_VERSION_MASK = 0xFFFF;
|
||||
constexpr auto CHUNK_TABLE_OFFSET = 28u;
|
||||
|
||||
struct FileRdefHeader
|
||||
@@ -50,7 +52,9 @@ namespace
|
||||
uint32_t constantBufferOffset;
|
||||
uint32_t boundResourceCount;
|
||||
uint32_t boundResourceOffset;
|
||||
uint32_t target;
|
||||
uint8_t minorVersion;
|
||||
uint8_t majorVersion;
|
||||
uint16_t type;
|
||||
uint32_t flags;
|
||||
uint32_t creatorOffset;
|
||||
};
|
||||
@@ -172,6 +176,17 @@ namespace
|
||||
D3D11_SRV_DIMENSION_BUFFEREX
|
||||
};
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_shader_input_flags
|
||||
enum D3D_SHADER_INPUT_FLAGS
|
||||
{
|
||||
D3D_SIF_USERPACKED = 0x1,
|
||||
D3D_SIF_COMPARISON_SAMPLER = 0x2,
|
||||
D3D_SIF_TEXTURE_COMPONENT_0 = 0x4,
|
||||
D3D_SIF_TEXTURE_COMPONENT_1 = 0x8,
|
||||
D3D_SIF_TEXTURE_COMPONENTS = 0xc,
|
||||
D3D_SIF_UNUSED = 0x10,
|
||||
};
|
||||
|
||||
struct FileBoundResource
|
||||
{
|
||||
uint32_t nameOffset;
|
||||
@@ -181,7 +196,7 @@ namespace
|
||||
uint32_t numSamples;
|
||||
uint32_t bindPoint;
|
||||
uint32_t bindCount;
|
||||
uint32_t uFlags;
|
||||
uint32_t uFlags; // D3D_SHADER_INPUT_FLAGS
|
||||
};
|
||||
|
||||
struct FileBoundResource_5_1 : FileBoundResource
|
||||
@@ -218,6 +233,15 @@ namespace
|
||||
D3D_CBUFFER_TYPE type;
|
||||
};
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_shader_variable_flags
|
||||
enum D3D_SHADER_VARIABLE_FLAGS
|
||||
{
|
||||
D3D_SVF_USERPACKED = 1,
|
||||
D3D_SVF_USED = 2,
|
||||
D3D_SVF_INTERFACE_POINTER = 4,
|
||||
D3D_SVF_INTERFACE_PARAMETER = 8,
|
||||
};
|
||||
|
||||
struct FileConstantBufferVariable
|
||||
{
|
||||
uint32_t nameOffset;
|
||||
@@ -230,13 +254,46 @@ namespace
|
||||
|
||||
struct FileConstantBufferVariable_5_0 : FileConstantBufferVariable
|
||||
{
|
||||
// Wine project does not seem to know what this is
|
||||
uint32_t unknown[4];
|
||||
uint32_t resourceBinding;
|
||||
uint32_t resourceCount;
|
||||
uint32_t samplerBinding;
|
||||
uint32_t samplerCount;
|
||||
};
|
||||
|
||||
static_assert(sizeof(FileConstantBufferVariable) == 24);
|
||||
static_assert(sizeof(FileConstantBufferVariable_5_0) == 40);
|
||||
|
||||
enum D3D_SHADER_VARIABLE_CLASS : uint16_t
|
||||
{
|
||||
D3D_SVC_SCALAR = 0,
|
||||
D3D_SVC_VECTOR,
|
||||
D3D_SVC_MATRIX_ROWS,
|
||||
D3D_SVC_MATRIX_COLUMNS,
|
||||
D3D_SVC_OBJECT,
|
||||
D3D_SVC_STRUCT,
|
||||
D3D_SVC_INTERFACE_CLASS,
|
||||
D3D_SVC_INTERFACE_POINTER,
|
||||
D3D10_SVC_SCALAR,
|
||||
D3D10_SVC_VECTOR,
|
||||
D3D10_SVC_MATRIX_ROWS,
|
||||
D3D10_SVC_MATRIX_COLUMNS,
|
||||
D3D10_SVC_OBJECT,
|
||||
D3D10_SVC_STRUCT,
|
||||
D3D11_SVC_INTERFACE_CLASS,
|
||||
D3D11_SVC_INTERFACE_POINTER
|
||||
};
|
||||
|
||||
struct FileRdefType
|
||||
{
|
||||
D3D_SHADER_VARIABLE_CLASS class_;
|
||||
uint16_t baseType;
|
||||
uint16_t rowCount;
|
||||
uint16_t columnCount;
|
||||
uint16_t elementCount;
|
||||
uint16_t fieldCount;
|
||||
uint32_t fieldsOffset;
|
||||
};
|
||||
|
||||
enum FileProgramType : uint32_t
|
||||
{
|
||||
D3D10_SB_PIXEL_SHADER = 0,
|
||||
@@ -261,6 +318,16 @@ namespace
|
||||
|
||||
static_assert(sizeof(FileShaderHeader) == 4);
|
||||
|
||||
constexpr bool IsAtLeastVersion(const uint8_t expectedMajor, const uint8_t expectedMinor, const uint8_t actualMajor, const uint8_t actualMinor)
|
||||
{
|
||||
if (actualMajor < expectedMajor)
|
||||
return false;
|
||||
if (actualMinor < expectedMinor)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t ReadU32(const uint8_t*& ptr)
|
||||
{
|
||||
const auto result = *reinterpret_cast<const uint32_t*>(ptr);
|
||||
@@ -451,6 +518,39 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
VariableClass GetVariableClass(const D3D_SHADER_VARIABLE_CLASS variableClass)
|
||||
{
|
||||
switch (variableClass)
|
||||
{
|
||||
case D3D_SVC_SCALAR:
|
||||
case D3D10_SVC_SCALAR:
|
||||
return VariableClass::SCALAR;
|
||||
case D3D_SVC_VECTOR:
|
||||
case D3D10_SVC_VECTOR:
|
||||
return VariableClass::VECTOR;
|
||||
case D3D_SVC_MATRIX_ROWS:
|
||||
case D3D10_SVC_MATRIX_ROWS:
|
||||
return VariableClass::MATRIX_ROWS;
|
||||
case D3D_SVC_MATRIX_COLUMNS:
|
||||
case D3D10_SVC_MATRIX_COLUMNS:
|
||||
return VariableClass::MATRIX_COLUMNS;
|
||||
case D3D_SVC_OBJECT:
|
||||
case D3D10_SVC_OBJECT:
|
||||
return VariableClass::OBJECT;
|
||||
case D3D_SVC_STRUCT:
|
||||
case D3D10_SVC_STRUCT:
|
||||
return VariableClass::STRUCT;
|
||||
case D3D_SVC_INTERFACE_CLASS:
|
||||
case D3D11_SVC_INTERFACE_CLASS:
|
||||
return VariableClass::INTERFACE_CLASS;
|
||||
case D3D_SVC_INTERFACE_POINTER:
|
||||
case D3D11_SVC_INTERFACE_POINTER:
|
||||
return VariableClass::INTERFACE_POINTER;
|
||||
default:
|
||||
return VariableClass::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
bool PopulateConstantBufferVariable(ConstantBufferVariable& constantBufferVariable,
|
||||
const FileConstantBufferVariable& fileConstantBufferVariable,
|
||||
const uint8_t* shaderByteCode,
|
||||
@@ -467,6 +567,17 @@ namespace
|
||||
constantBufferVariable.m_offset = fileConstantBufferVariable.startOffset;
|
||||
constantBufferVariable.m_size = fileConstantBufferVariable.size;
|
||||
constantBufferVariable.m_flags = fileConstantBufferVariable.flags;
|
||||
constantBufferVariable.m_is_used = fileConstantBufferVariable.flags & D3D_SVF_USED;
|
||||
|
||||
if (fileConstantBufferVariable.typeOffset + sizeof(FileRdefType) > chunkSize)
|
||||
return false;
|
||||
|
||||
const auto type = reinterpret_cast<const FileRdefType*>(shaderByteCode + chunkOffset + fileConstantBufferVariable.typeOffset);
|
||||
|
||||
constantBufferVariable.m_variable_class = GetVariableClass(type->class_);
|
||||
constantBufferVariable.m_element_count = static_cast<uint16_t>(type->elementCount);
|
||||
constantBufferVariable.m_column_count = static_cast<uint16_t>(type->columnCount);
|
||||
constantBufferVariable.m_row_count = static_cast<uint16_t>(type->rowCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -500,7 +611,8 @@ namespace
|
||||
const size_t shaderByteCodeSize,
|
||||
const size_t chunkOffset,
|
||||
const size_t chunkSize,
|
||||
const unsigned targetVersion)
|
||||
const uint8_t major,
|
||||
const uint8_t minor)
|
||||
{
|
||||
const auto nameString = reinterpret_cast<const char*>(shaderByteCode + chunkOffset + fileConstantBuffer.nameOffset);
|
||||
|
||||
@@ -513,10 +625,10 @@ namespace
|
||||
constantBuffer.m_flags = fileConstantBuffer.flags;
|
||||
constantBuffer.m_type = GetType(fileConstantBuffer.type);
|
||||
|
||||
if (targetVersion < VERSION_5_0)
|
||||
if (IsAtLeastVersion(5, 0, major, minor))
|
||||
{
|
||||
const auto* variables = reinterpret_cast<const FileConstantBufferVariable*>(shaderByteCode + chunkOffset + fileConstantBuffer.variableOffset);
|
||||
if (fileConstantBuffer.variableOffset + sizeof(FileConstantBufferVariable) * fileConstantBuffer.variableCount > chunkSize)
|
||||
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++)
|
||||
@@ -532,8 +644,8 @@ namespace
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* variables = reinterpret_cast<const FileConstantBufferVariable_5_0*>(shaderByteCode + chunkOffset + fileConstantBuffer.variableOffset);
|
||||
if (fileConstantBuffer.variableOffset + sizeof(FileConstantBufferVariable_5_0) * fileConstantBuffer.variableCount > chunkSize)
|
||||
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++)
|
||||
@@ -562,7 +674,6 @@ namespace
|
||||
|
||||
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))
|
||||
@@ -570,23 +681,7 @@ namespace
|
||||
|
||||
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
|
||||
if (IsAtLeastVersion(5, 1, header->majorVersion, header->minorVersion))
|
||||
{
|
||||
const auto* boundResources = reinterpret_cast<const FileBoundResource_5_1*>(shaderByteCode + chunkOffset + header->boundResourceOffset);
|
||||
if (header->boundResourceOffset + sizeof(FileBoundResource_5_1) * header->boundResourceCount > chunkSize)
|
||||
@@ -603,6 +698,22 @@ namespace
|
||||
shaderInfo.m_bound_resources.emplace_back(std::move(boundResource));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
const auto* constantBuffers = reinterpret_cast<const FileConstantBuffer*>(shaderByteCode + chunkOffset + header->constantBufferOffset);
|
||||
if (header->constantBufferOffset + sizeof(FileConstantBuffer) * header->constantBufferCount > chunkSize)
|
||||
@@ -613,7 +724,8 @@ namespace
|
||||
const auto& fileConstantBuffer = constantBuffers[constantBufferIndex];
|
||||
ConstantBuffer constantBuffer;
|
||||
|
||||
if (!PopulateConstantBuffer(constantBuffer, fileConstantBuffer, shaderByteCode, shaderByteCodeSize, chunkOffset, chunkSize, targetVersion))
|
||||
if (!PopulateConstantBuffer(
|
||||
constantBuffer, fileConstantBuffer, shaderByteCode, shaderByteCodeSize, chunkOffset, chunkSize, header->majorVersion, header->minorVersion))
|
||||
return false;
|
||||
|
||||
shaderInfo.m_constant_buffers.emplace_back(std::move(constantBuffer));
|
||||
@@ -684,5 +796,5 @@ std::unique_ptr<ShaderInfo> ShaderAnalyser::GetShaderInfo(const void* shader, co
|
||||
if (!PopulateShaderInfoFromBytes(*shaderInfo, static_cast<const uint8_t*>(shader), shaderSize))
|
||||
return nullptr;
|
||||
|
||||
return shaderInfo;
|
||||
return std::move(shaderInfo);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,19 @@ namespace d3d11
|
||||
COMPUTE_SHADER
|
||||
};
|
||||
|
||||
enum class VariableClass : std::uint8_t
|
||||
{
|
||||
UNKNOWN,
|
||||
SCALAR,
|
||||
VECTOR,
|
||||
MATRIX_ROWS,
|
||||
MATRIX_COLUMNS,
|
||||
OBJECT,
|
||||
STRUCT,
|
||||
INTERFACE_CLASS,
|
||||
INTERFACE_POINTER
|
||||
};
|
||||
|
||||
class ConstantBufferVariable
|
||||
{
|
||||
public:
|
||||
@@ -32,6 +45,11 @@ namespace d3d11
|
||||
unsigned m_offset;
|
||||
unsigned m_size;
|
||||
unsigned m_flags;
|
||||
bool m_is_used;
|
||||
VariableClass m_variable_class;
|
||||
std::uint16_t m_element_count;
|
||||
std::uint16_t m_row_count;
|
||||
std::uint16_t m_column_count;
|
||||
};
|
||||
|
||||
enum class ConstantBufferType : std::uint8_t
|
||||
|
||||
Reference in New Issue
Block a user