#include "TechsetDumperT6.h" #include "Game/T6/Material/MaterialConstantZoneStateT6.h" #include "Game/T6/Techset/TechsetConstantsT6.h" #include "Shader/ShaderCommon.h" #include "Techset/CommonTechniqueDumper.h" #include "Techset/CommonTechsetDumper.h" #include "Techset/ShaderDumpingZoneState.h" #include "Techset/TechniqueDumpingZoneState.h" #include using namespace T6; namespace { void DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader& pixelShader) { const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(pixelShader.name)); if (!shaderFile) return; shaderFile->write(pixelShader.prog.loadDef.program, pixelShader.prog.loadDef.programSize); } void DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader& vertexShader) { const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(vertexShader.name)); if (!shaderFile) return; shaderFile->write(vertexShader.prog.loadDef.program, vertexShader.prog.loadDef.programSize); } void DumpShaders(AssetDumpingContext& context, const MaterialTechniqueSet& techset) { auto* shaderState = context.GetZoneAssetDumperState(); for (const auto* technique : techset.techniques) { if (!technique || !shaderState->ShouldDumpTechnique(technique)) continue; for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++) { const auto* pixelShader = technique->passArray[passIndex].pixelShader; if (pixelShader && shaderState->ShouldDumpPixelShader(pixelShader)) DumpPixelShader(context, *pixelShader); const auto* vertexShader = technique->passArray[passIndex].vertexShader; if (vertexShader && shaderState->ShouldDumpVertexShader(vertexShader)) DumpVertexShader(context, *vertexShader); } } } techset::CommonVertexDeclaration ConvertToCommonVertexDeclaration(const MaterialVertexDeclaration* vertexDecl) { std::vector commonRouting; if (vertexDecl) { const auto streamCount = std::min(static_cast(vertexDecl->streamCount), std::extent_v); for (auto streamIndex = 0u; streamIndex < streamCount; streamIndex++) { const auto& routing = vertexDecl->routing.data[streamIndex]; commonRouting.emplace_back(techset::CommonStreamRouting{ .m_source = static_cast(routing.source), .m_destination = static_cast(routing.dest), }); } } return techset::CommonVertexDeclaration{ .m_routing = std::move(commonRouting), }; } techset::CommonShaderArg ConvertToCommonArg(const MaterialShaderArgument& arg) { switch (arg.type) { case MTL_ARG_CODE_VERTEX_CONST: case MTL_ARG_CODE_PIXEL_CONST: return techset::CommonShaderArg{ .m_type = techset::CommonShaderArgType::CODE_CONST, .m_destination = {.dx11 = { .m_location = arg.location.offset, .m_size = arg.size, .m_buffer = arg.buffer, }}, .m_value = { .code_const_source = static_cast(arg.u.codeConst.index), } }; case MTL_ARG_MATERIAL_VERTEX_CONST: case MTL_ARG_MATERIAL_PIXEL_CONST: return techset::CommonShaderArg{ .m_type = techset::CommonShaderArgType::MATERIAL_CONST, .m_destination = {.dx11 = { .m_location = arg.location.offset, .m_size = arg.size, .m_buffer = arg.buffer, }}, .m_value = { .name_hash = arg.u.nameHash, } }; case MTL_ARG_CODE_PIXEL_SAMPLER: return techset::CommonShaderArg{ .m_type = techset::CommonShaderArgType::CODE_SAMPLER, .m_destination = {.dx11 = { .m_location = arg.location.samplerIndex, .m_size = arg.size, .m_buffer = arg.buffer, }}, .m_value = { .code_sampler_source = static_cast(arg.u.codeSampler), } }; case MTL_ARG_MATERIAL_PIXEL_SAMPLER: return techset::CommonShaderArg{ .m_type = techset::CommonShaderArgType::MATERIAL_SAMPLER, .m_destination = {.dx11 = { .m_location = arg.location.samplerIndex, .m_size = arg.size, .m_buffer = arg.buffer, }}, .m_value = { .name_hash = arg.u.nameHash, } }; default: case MTL_ARG_LITERAL_VERTEX_CONST: case MTL_ARG_LITERAL_PIXEL_CONST: if (arg.u.literalConst) { return techset::CommonShaderArg{ .m_type = techset::CommonShaderArgType::LITERAL_CONST, .m_destination = {.dx11 = { .m_location = arg.location.offset, .m_size = arg.size, .m_buffer = arg.buffer, }}, .m_value = { .literal_value = { (*arg.u.literalConst)[0], (*arg.u.literalConst)[1], (*arg.u.literalConst)[2], (*arg.u.literalConst)[3], }, } }; } return techset::CommonShaderArg{ .m_type = techset::CommonShaderArgType::LITERAL_CONST, .m_destination = {.dx11 = { .m_location = arg.location.offset, .m_size = arg.size, .m_buffer = arg.buffer, }}, .m_value = {}, }; } } techset::CommonTechniqueShader ConvertToCommonShader(const MaterialPass& pass, const MaterialVertexShader* vertexShader) { techset::CommonTechniqueShader result{}; if (!vertexShader) return result; if (vertexShader->name) result.m_name = vertexShader->name; if (vertexShader->prog.loadDef.program) { result.m_shader_bin = vertexShader->prog.loadDef.program; result.m_shader_bin_size = vertexShader->prog.loadDef.programSize; } if (pass.args) { const size_t totalArgCount = pass.perPrimArgCount + pass.perObjArgCount + pass.stableArgCount; for (auto argIndex = 0uz; argIndex < totalArgCount; argIndex++) { const auto& arg = pass.args[argIndex]; switch (arg.type) { case MTL_ARG_CODE_VERTEX_CONST: case MTL_ARG_MATERIAL_VERTEX_CONST: case MTL_ARG_LITERAL_VERTEX_CONST: result.m_args.emplace_back(ConvertToCommonArg(arg)); break; default: break; } } } return result; } techset::CommonTechniqueShader ConvertToCommonShader(const MaterialPass& pass, const MaterialPixelShader* pixelShader) { techset::CommonTechniqueShader result{}; if (!pixelShader) return result; if (pixelShader->name) result.m_name = pixelShader->name; if (pixelShader->prog.loadDef.program) { result.m_shader_bin = pixelShader->prog.loadDef.program; result.m_shader_bin_size = pixelShader->prog.loadDef.programSize; } if (pass.args) { const size_t totalArgCount = pass.perPrimArgCount + pass.perObjArgCount + pass.stableArgCount; for (auto argIndex = 0uz; argIndex < totalArgCount; argIndex++) { const auto& arg = pass.args[argIndex]; switch (arg.type) { case MTL_ARG_CODE_PIXEL_CONST: case MTL_ARG_CODE_PIXEL_SAMPLER: case MTL_ARG_MATERIAL_PIXEL_CONST: case MTL_ARG_MATERIAL_PIXEL_SAMPLER: case MTL_ARG_LITERAL_PIXEL_CONST: result.m_args.emplace_back(ConvertToCommonArg(arg)); break; default: break; } } } return result; } techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique) { std::vector passes; for (auto passIndex = 0u; passIndex < technique.passCount; passIndex++) { const auto& pass = technique.passArray[passIndex]; passes.emplace_back(techset::CommonPass{ .m_sampler_flags = pass.customSamplerFlags, .m_dx_version = techset::DxVersion::DX11, .m_vertex_shader = ConvertToCommonShader(pass, pass.vertexShader), .m_pixel_shader = ConvertToCommonShader(pass, pass.pixelShader), .m_vertex_declaration = ConvertToCommonVertexDeclaration(pass.vertexDecl), }); } return techset::CommonTechnique{ .m_name = technique.name ? technique.name : std::string(), .m_flags = technique.flags, .m_passes = std::move(passes), }; } void DumpTechniques(AssetDumpingContext& context, const MaterialTechniqueSet& techset) { static techset::CommonCodeSourceInfos codeSourceInfos(commonCodeConstSources, std::extent_v, commonCodeSamplerSources, std::extent_v); static techset::CommonStreamRoutingInfos routingInfos( streamRoutingSources, std::extent_v, streamRoutingDestinations, std::extent_v); auto* techniqueState = context.GetZoneAssetDumperState(); const auto* materialConstantState = context.GetZoneAssetDumperState(); for (const auto* technique : techset.techniques) { if (technique && techniqueState->ShouldDumpTechnique(technique)) { const auto commonTechnique = ConvertToCommonTechnique(*technique); techset::DumpCommonTechnique(context, commonTechnique, codeSourceInfos, routingInfos, *materialConstantState); } } } techset::CommonTechset ConvertToCommonTechset(const MaterialTechniqueSet& techset) { std::vector techniqueNames(std::extent_v); for (auto techniqueIndex = 0u; techniqueIndex < std::extent_v; techniqueIndex++) { const auto* technique = techset.techniques[techniqueIndex]; if (technique && technique->name) techniqueNames[techniqueIndex] = technique->name; } return techset::CommonTechset{ .m_name = techset.name, .m_technique_names = std::move(techniqueNames), }; } void DumpTechset(const AssetDumpingContext& context, const MaterialTechniqueSet& techset) { static techset::CommonTechniqueTypeNames commonNames(techniqueTypeNames, std::extent_v); const auto commonTechset = ConvertToCommonTechset(techset); techset::DumpCommonTechset(commonNames, context, commonTechset); } } // namespace namespace techset { DumperT6::DumperT6(const AssetPool& pool) : AbstractAssetDumper(pool) { } void DumperT6::Dump(AssetDumpingContext& context) { context.GetZoneAssetDumperState()->EnsureInitialized(); AbstractAssetDumper::Dump(context); } void DumperT6::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) { const auto* techniqueSet = asset.Asset(); DumpTechset(context, *techniqueSet); DumpTechniques(context, *techniqueSet); DumpShaders(context, *techniqueSet); } } // namespace techset