mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-05-17 07:21:43 +00:00
fix: errors with common techset dumping
* not respecting transposing matrices * not respecting arrays
This commit is contained in:
@@ -13,20 +13,16 @@ using namespace techset;
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class TechniqueShaderType : std::uint8_t
|
||||
{
|
||||
VERTEX_SHADER,
|
||||
PIXEL_SHADER
|
||||
};
|
||||
|
||||
class TechniqueFileWriter : public AbstractTextDumper
|
||||
{
|
||||
public:
|
||||
TechniqueFileWriter(std::ostream& stream,
|
||||
const DxVersion dxVersion,
|
||||
const CommonCodeSourceInfos& codeSourceInfos,
|
||||
const CommonStreamRoutingInfos& routingInfos,
|
||||
const AbstractMaterialConstantZoneState& constantZoneState)
|
||||
: AbstractTextDumper(stream),
|
||||
m_dx_version(dxVersion),
|
||||
m_code_source_infos(codeSourceInfos),
|
||||
m_routing_infos(routingInfos),
|
||||
m_constant_zone_state(constantZoneState)
|
||||
@@ -73,8 +69,8 @@ namespace
|
||||
#endif
|
||||
|
||||
DumpStateMap();
|
||||
DumpShader(technique, pass.m_vertex_shader, TechniqueShaderType::VERTEX_SHADER, pass.m_dx_version);
|
||||
DumpShader(technique, pass.m_pixel_shader, TechniqueShaderType::PIXEL_SHADER, pass.m_dx_version);
|
||||
DumpShader(technique, pass, pass.m_vertex_shader, CommonTechniqueShaderType::VERTEX, m_dx_version);
|
||||
DumpShader(technique, pass, pass.m_pixel_shader, CommonTechniqueShaderType::PIXEL, m_dx_version);
|
||||
DumpVertexDecl(pass.m_vertex_declaration);
|
||||
|
||||
DecIndent();
|
||||
@@ -89,9 +85,13 @@ namespace
|
||||
m_stream << "stateMap \"passthrough\"; // TODO\n";
|
||||
}
|
||||
|
||||
void DumpShader(const CommonTechnique& technique, const CommonTechniqueShader& shader, const TechniqueShaderType shaderType, const DxVersion dxVersion)
|
||||
void DumpShader(const CommonTechnique& technique,
|
||||
const CommonPass& pass,
|
||||
const CommonTechniqueShader& shader,
|
||||
const CommonTechniqueShaderType shaderType,
|
||||
const DxVersion dxVersion)
|
||||
{
|
||||
if (!shader.m_shader_bin)
|
||||
if (!shader.m_bin || !shader.m_bin->m_shader_bin)
|
||||
{
|
||||
if (!shader.m_name.empty())
|
||||
{
|
||||
@@ -105,7 +105,7 @@ namespace
|
||||
unsigned versionMajor, versionMinor;
|
||||
if (dxVersion == DxVersion::DX9)
|
||||
{
|
||||
const auto shaderInfo = d3d9::ShaderAnalyser::GetShaderInfo(shader.m_shader_bin, shader.m_shader_bin_size);
|
||||
const auto shaderInfo = d3d9::ShaderAnalyser::GetShaderInfo(shader.m_bin->m_shader_bin, shader.m_bin->m_shader_bin_size);
|
||||
assert(shaderInfo);
|
||||
if (!shaderInfo)
|
||||
return;
|
||||
@@ -115,13 +115,16 @@ namespace
|
||||
|
||||
DumpShaderHeader(shader, shaderType, versionMajor, versionMinor);
|
||||
|
||||
for (const auto& arg : shader.m_args)
|
||||
DumpShaderArgDx9(technique, arg, *shaderInfo);
|
||||
for (const auto& arg : pass.m_args)
|
||||
{
|
||||
if (arg.m_type.m_shader_type == shaderType)
|
||||
DumpShaderArgDx9(technique, arg, *shaderInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(dxVersion == DxVersion::DX11);
|
||||
const auto shaderInfo = d3d11::ShaderAnalyser::GetShaderInfo(shader.m_shader_bin, shader.m_shader_bin_size);
|
||||
const auto shaderInfo = d3d11::ShaderAnalyser::GetShaderInfo(shader.m_bin->m_shader_bin, shader.m_bin->m_shader_bin_size);
|
||||
assert(shaderInfo);
|
||||
if (!shaderInfo)
|
||||
return;
|
||||
@@ -131,8 +134,11 @@ namespace
|
||||
|
||||
DumpShaderHeader(shader, shaderType, versionMajor, versionMinor);
|
||||
|
||||
for (const auto& arg : shader.m_args)
|
||||
DumpShaderArgDx11(technique, arg, *shaderInfo);
|
||||
for (const auto& arg : pass.m_args)
|
||||
{
|
||||
if (arg.m_type.m_shader_type == shaderType)
|
||||
DumpShaderArgDx11(technique, arg, *shaderInfo);
|
||||
}
|
||||
}
|
||||
|
||||
DecIndent();
|
||||
@@ -140,9 +146,9 @@ namespace
|
||||
m_stream << "}\n";
|
||||
}
|
||||
|
||||
void DumpShaderHeader(const CommonTechniqueShader& shader, const TechniqueShaderType shaderType, unsigned versionMajor, unsigned versionMinor)
|
||||
void DumpShaderHeader(const CommonTechniqueShader& shader, const CommonTechniqueShaderType shaderType, unsigned versionMajor, unsigned versionMinor)
|
||||
{
|
||||
const auto shaderTypeName = shaderType == TechniqueShaderType::VERTEX_SHADER ? "vertexShader" : "pixelShader";
|
||||
const auto shaderTypeName = shaderType == CommonTechniqueShaderType::VERTEX ? "vertexShader" : "pixelShader";
|
||||
|
||||
m_stream << "\n";
|
||||
Indent();
|
||||
@@ -154,9 +160,10 @@ namespace
|
||||
|
||||
void DumpShaderArgDx9(const CommonTechnique& technique, const CommonShaderArg& arg, const d3d9::ShaderInfo& shaderInfo) const
|
||||
{
|
||||
const auto expectedRegisterSet = arg.m_type == CommonShaderArgType::CODE_SAMPLER || arg.m_type == CommonShaderArgType::MATERIAL_SAMPLER
|
||||
? d3d9::RegisterSet::SAMPLER
|
||||
: d3d9::RegisterSet::FLOAT_4;
|
||||
const auto expectedRegisterSet =
|
||||
arg.m_type.m_value_type == CommonShaderValueType::CODE_SAMPLER || arg.m_type.m_value_type == CommonShaderValueType::MATERIAL_SAMPLER
|
||||
? d3d9::RegisterSet::SAMPLER
|
||||
: d3d9::RegisterSet::FLOAT_4;
|
||||
const auto destinationRegister = arg.m_destination.dx9.m_destination_register;
|
||||
const auto targetShaderArg = std::ranges::find_if(shaderInfo.m_constants,
|
||||
[destinationRegister, expectedRegisterSet](const d3d9::ShaderConstant& constant)
|
||||
@@ -170,11 +177,11 @@ namespace
|
||||
if (targetShaderArg == shaderInfo.m_constants.end())
|
||||
{
|
||||
Indent();
|
||||
m_stream << std::format("// Unrecognized arg dest: {} type: {}\n", destinationRegister, static_cast<unsigned>(arg.m_type));
|
||||
m_stream << std::format("// Unrecognized arg dest: {} type: {}\n", destinationRegister, static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
con::error("Technique {}: Could not find arg (type: {}; dest: {}) in shader",
|
||||
technique.m_name,
|
||||
destinationRegister,
|
||||
static_cast<unsigned>(arg.m_type));
|
||||
static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -186,14 +193,14 @@ namespace
|
||||
else
|
||||
codeDestAccessor = targetShaderArg->m_name;
|
||||
|
||||
DumpShaderArg(technique, arg, codeDestAccessor);
|
||||
const auto isTransposed = targetShaderArg->m_class == d3d9::ParameterClass::MATRIX_COLUMNS;
|
||||
DumpShaderArg(technique, arg, codeDestAccessor, isTransposed);
|
||||
}
|
||||
|
||||
void DumpShaderArgDx11(const CommonTechnique& technique, const CommonShaderArg& arg, const d3d11::ShaderInfo& shaderInfo) const
|
||||
{
|
||||
const auto& destination = arg.m_destination.dx11;
|
||||
if (arg.m_type == CommonShaderArgType::CODE_CONST || arg.m_type == CommonShaderArgType::MATERIAL_CONST
|
||||
|| arg.m_type == CommonShaderArgType::LITERAL_CONST)
|
||||
if (IsConstValueType(arg.m_type.m_value_type))
|
||||
{
|
||||
const auto boundResource = std::ranges::find_if(shaderInfo.m_bound_resources,
|
||||
[destination](const d3d11::BoundResource& resource)
|
||||
@@ -207,13 +214,13 @@ namespace
|
||||
Indent();
|
||||
m_stream << std::format("// Could not find bound resource for arg buffer: {} offset: {} type: {}\n",
|
||||
destination.m_buffer,
|
||||
destination.m_location,
|
||||
static_cast<unsigned>(arg.m_type));
|
||||
destination.m_location.constant_buffer_offset,
|
||||
static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
con::error("Technique {}: Could not find bound resource for arg (buffer: {} offset: {} type: {}) in shader",
|
||||
technique.m_name,
|
||||
destination.m_buffer,
|
||||
destination.m_location,
|
||||
static_cast<unsigned>(arg.m_type));
|
||||
destination.m_location.constant_buffer_offset,
|
||||
static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
return;
|
||||
}
|
||||
const auto buffer = std::ranges::find_if(shaderInfo.m_constant_buffers,
|
||||
@@ -229,75 +236,112 @@ namespace
|
||||
return;
|
||||
}
|
||||
|
||||
const auto variable = std::ranges::find_if(buffer->m_variables,
|
||||
[destination](const d3d11::ConstantBufferVariable& var)
|
||||
{
|
||||
return var.m_offset <= destination.m_location
|
||||
&& var.m_offset + var.m_size >= destination.m_location + destination.m_size;
|
||||
});
|
||||
const auto variable =
|
||||
std::ranges::find_if(buffer->m_variables,
|
||||
[destination](const d3d11::ConstantBufferVariable& var)
|
||||
{
|
||||
return var.m_offset <= destination.m_location.constant_buffer_offset
|
||||
&& var.m_offset + var.m_size >= destination.m_location.constant_buffer_offset + destination.m_size;
|
||||
});
|
||||
if (variable == buffer->m_variables.end())
|
||||
{
|
||||
Indent();
|
||||
m_stream << std::format("// Could not find variable in buffer: {} offset: {} type: {}\n",
|
||||
buffer->m_name,
|
||||
destination.m_location,
|
||||
static_cast<unsigned>(arg.m_type));
|
||||
destination.m_location.constant_buffer_offset,
|
||||
static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
con::error("Technique {}: Could not find variable in buffer for arg (buffer: {} offset: {} type: {}) in shader",
|
||||
technique.m_name,
|
||||
buffer->m_name,
|
||||
destination.m_location,
|
||||
static_cast<unsigned>(arg.m_type));
|
||||
destination.m_location.constant_buffer_offset,
|
||||
static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
return;
|
||||
}
|
||||
|
||||
DumpShaderArg(technique, arg, variable->m_name);
|
||||
std::string codeDestAccessor;
|
||||
if (variable->m_element_count <= 1)
|
||||
{
|
||||
codeDestAccessor = variable->m_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto elementSize = variable->m_size / variable->m_element_count;
|
||||
|
||||
// Assert destination is aligned with element size
|
||||
assert((destination.m_location.constant_buffer_offset - variable->m_offset) % elementSize == 0);
|
||||
|
||||
const auto destinationIndex = (destination.m_location.constant_buffer_offset - variable->m_offset) / elementSize;
|
||||
|
||||
codeDestAccessor = std::format("{}[{}]", variable->m_name, destinationIndex);
|
||||
}
|
||||
|
||||
const auto isTransposed = variable->m_variable_class == d3d11::VariableClass::MATRIX_COLUMNS;
|
||||
DumpShaderArg(technique, arg, codeDestAccessor, isTransposed);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(arg.m_type == CommonShaderArgType::CODE_SAMPLER || arg.m_type == CommonShaderArgType::MATERIAL_SAMPLER);
|
||||
assert(IsSamplerValueType(arg.m_type.m_value_type));
|
||||
|
||||
const auto boundResource = std::ranges::find_if(shaderInfo.m_bound_resources,
|
||||
[destination](const d3d11::BoundResource& resource)
|
||||
{
|
||||
return (resource.m_type == d3d11::BoundResourceType::SAMPLER
|
||||
|| resource.m_type == d3d11::BoundResourceType::TEXTURE)
|
||||
&& resource.m_bind_point == destination.m_location;
|
||||
});
|
||||
if (boundResource == shaderInfo.m_bound_resources.end())
|
||||
// The game seems to guarantee the texture name to be the accurate one
|
||||
const auto boundTextureResource = std::ranges::find_if(shaderInfo.m_bound_resources,
|
||||
[destination](const d3d11::BoundResource& resource)
|
||||
{
|
||||
if (resource.m_type == d3d11::BoundResourceType::TEXTURE)
|
||||
return resource.m_bind_point == destination.m_location.texture_index;
|
||||
|
||||
return false;
|
||||
});
|
||||
if (boundTextureResource == shaderInfo.m_bound_resources.end())
|
||||
{
|
||||
Indent();
|
||||
m_stream << std::format("// Could not find buffer for arg buffer: {} offset: {} type: {}\n",
|
||||
m_stream << std::format("// Could not find buffer for arg buffer: {} sampler: {} texture: {} type: {}\n",
|
||||
destination.m_buffer,
|
||||
destination.m_location,
|
||||
static_cast<unsigned>(arg.m_type));
|
||||
con::error("Technique {}: Could not find buffer for arg (buffer: {} offset: {} type: {}) in shader",
|
||||
destination.m_location.sampler_index,
|
||||
destination.m_location.texture_index,
|
||||
static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
con::error("Technique {}: Could not find buffer for arg (buffer: {} sampler: {} texture: {} type: {}) in shader",
|
||||
technique.m_name,
|
||||
destination.m_buffer,
|
||||
destination.m_location,
|
||||
static_cast<unsigned>(arg.m_type));
|
||||
destination.m_location.sampler_index,
|
||||
destination.m_location.texture_index,
|
||||
static_cast<unsigned>(arg.m_type.m_value_type));
|
||||
return;
|
||||
}
|
||||
DumpShaderArg(technique, arg, boundResource->m_name);
|
||||
DumpShaderArg(technique, arg, boundTextureResource->m_name, false);
|
||||
}
|
||||
}
|
||||
|
||||
void DumpShaderArg(const CommonTechnique& technique, const CommonShaderArg& arg, std::string codeDestAccessor) const
|
||||
void DumpShaderArg(const CommonTechnique& technique, const CommonShaderArg& arg, std::string codeDestAccessor, const bool isTransposed) const
|
||||
{
|
||||
if (arg.m_type == CommonShaderArgType::CODE_CONST)
|
||||
if (arg.m_type.m_value_type == CommonShaderValueType::CODE_CONST)
|
||||
{
|
||||
const auto constSourceInfo = m_code_source_infos.GetInfoForCodeConstSource(arg.m_value.code_const_source);
|
||||
auto constSourceInfo = m_code_source_infos.GetInfoForCodeConstSource(arg.m_value.code_const_source.m_index);
|
||||
|
||||
if (isTransposed)
|
||||
{
|
||||
assert(constSourceInfo);
|
||||
if (constSourceInfo && constSourceInfo->transposedMatrix)
|
||||
constSourceInfo = m_code_source_infos.GetInfoForCodeConstSource(*constSourceInfo->transposedMatrix);
|
||||
}
|
||||
|
||||
if (constSourceInfo)
|
||||
{
|
||||
if (codeDestAccessor != constSourceInfo->accessor)
|
||||
std::string codeAccessor;
|
||||
if (constSourceInfo->arrayCount <= 1)
|
||||
codeAccessor = constSourceInfo->accessor;
|
||||
else
|
||||
codeAccessor = std::format("{}[{}]", constSourceInfo->accessor, arg.m_value.code_const_source.m_index - constSourceInfo->value);
|
||||
|
||||
if (codeDestAccessor != codeAccessor)
|
||||
{
|
||||
Indent();
|
||||
m_stream << std::format("{} = constant.{};\n", codeDestAccessor, constSourceInfo->accessor);
|
||||
m_stream << std::format("{} = constant.{};\n", codeDestAccessor, codeAccessor);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TECHSET_DEBUG
|
||||
Indent();
|
||||
m_stream << std::format("// Omitted due to matching accessors: {} = constant.{};\n", codeDestAccessor, constSourceInfo->accessor);
|
||||
m_stream << std::format("// Omitted due to matching accessors: {} = constant.{};\n", codeDestAccessor, codeAccessor);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -309,7 +353,7 @@ namespace
|
||||
con::error("Technique {}: Could not find code source info for const {}", technique.m_name, codeDestAccessor);
|
||||
}
|
||||
}
|
||||
else if (arg.m_type == CommonShaderArgType::CODE_SAMPLER)
|
||||
else if (arg.m_type.m_value_type == CommonShaderValueType::CODE_SAMPLER)
|
||||
{
|
||||
const auto samplerSourceInfo = m_code_source_infos.GetInfoForCodeSamplerSource(arg.m_value.code_sampler_source);
|
||||
if (samplerSourceInfo)
|
||||
@@ -335,7 +379,7 @@ namespace
|
||||
con::error("Technique {}: Could not find code source info for sampler {}", technique.m_name, codeDestAccessor);
|
||||
}
|
||||
}
|
||||
else if (arg.m_type == CommonShaderArgType::LITERAL_CONST)
|
||||
else if (arg.m_type.m_value_type == CommonShaderValueType::LITERAL_CONST)
|
||||
{
|
||||
Indent();
|
||||
m_stream << std::format("{} = float4({}, {}, {}, {});\n",
|
||||
@@ -345,7 +389,7 @@ namespace
|
||||
arg.m_value.literal_value[2],
|
||||
arg.m_value.literal_value[3]);
|
||||
}
|
||||
else if (arg.m_type == CommonShaderArgType::MATERIAL_CONST || arg.m_type == CommonShaderArgType::MATERIAL_SAMPLER)
|
||||
else if (arg.m_type.m_value_type == CommonShaderValueType::MATERIAL_CONST || arg.m_type.m_value_type == CommonShaderValueType::MATERIAL_SAMPLER)
|
||||
{
|
||||
Indent();
|
||||
|
||||
@@ -385,6 +429,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
DxVersion m_dx_version;
|
||||
const CommonCodeSourceInfos& m_code_source_infos;
|
||||
const CommonStreamRoutingInfos& m_routing_infos;
|
||||
const AbstractMaterialConstantZoneState& m_constant_zone_state;
|
||||
@@ -395,6 +440,7 @@ namespace techset
|
||||
{
|
||||
void DumpCommonTechnique(const AssetDumpingContext& context,
|
||||
const CommonTechnique& technique,
|
||||
const DxVersion dxVersion,
|
||||
const CommonCodeSourceInfos& codeSourceInfos,
|
||||
const CommonStreamRoutingInfos& routingInfos,
|
||||
const AbstractMaterialConstantZoneState& constantZoneState)
|
||||
@@ -402,7 +448,7 @@ namespace techset
|
||||
const auto techniqueFile = context.OpenAssetFile(GetFileNameForTechniqueName(technique.m_name));
|
||||
if (techniqueFile)
|
||||
{
|
||||
TechniqueFileWriter writer(*techniqueFile, codeSourceInfos, routingInfos, constantZoneState);
|
||||
TechniqueFileWriter writer(*techniqueFile, dxVersion, codeSourceInfos, routingInfos, constantZoneState);
|
||||
writer.DumpTechnique(technique);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace techset
|
||||
{
|
||||
void DumpCommonTechnique(const AssetDumpingContext& context,
|
||||
const CommonTechnique& technique,
|
||||
DxVersion dxVersion,
|
||||
const CommonCodeSourceInfos& codeSourceInfos,
|
||||
const CommonStreamRoutingInfos& routingInfos,
|
||||
const AbstractMaterialConstantZoneState& constantZoneState);
|
||||
|
||||
Reference in New Issue
Block a user