Avoid string reallocation in swizzle CgBinaryProgram

This commit is contained in:
sampletext32 2020-06-05 17:35:53 +03:00 committed by kd-11
parent 731d4330fe
commit 0ad4e91001
3 changed files with 88 additions and 54 deletions

View file

@ -47,18 +47,17 @@ void CgBinaryDisasm::AddCodeAsm(const std::string& code)
std::string CgBinaryDisasm::GetMask() std::string CgBinaryDisasm::GetMask()
{ {
std::string ret; std::string ret;
ret.reserve(5);
static const char dst_mask[4] = static constexpr std::string_view dst_mask = "xyzw";
{
'x', 'y', 'z', 'w'
};
ret += '.';
if (dst.mask_x) ret += dst_mask[0]; if (dst.mask_x) ret += dst_mask[0];
if (dst.mask_y) ret += dst_mask[1]; if (dst.mask_y) ret += dst_mask[1];
if (dst.mask_z) ret += dst_mask[2]; if (dst.mask_z) ret += dst_mask[2];
if (dst.mask_w) ret += dst_mask[3]; if (dst.mask_w) ret += dst_mask[3];
return ret.empty() || strncmp(ret.c_str(), dst_mask, 4) == 0 ? "" : ("." + ret); return ret == "."sv || ret == ".xyzw"sv ? "" : (ret);
} }
std::string CgBinaryDisasm::AddRegDisAsm(u32 index, int fp16) std::string CgBinaryDisasm::AddRegDisAsm(u32 index, int fp16)
@ -86,20 +85,25 @@ std::string CgBinaryDisasm::AddTexDisAsm()
std::string CgBinaryDisasm::GetCondDisAsm() std::string CgBinaryDisasm::GetCondDisAsm()
{ {
static const char f[4] = { 'x', 'y', 'z', 'w' }; static constexpr std::string_view f = "xyzw";
std::string swizzle, cond; std::string swizzle, cond;
swizzle.reserve(5);
swizzle += '.';
swizzle += f[src0.cond_swizzle_x]; swizzle += f[src0.cond_swizzle_x];
swizzle += f[src0.cond_swizzle_y]; swizzle += f[src0.cond_swizzle_y];
swizzle += f[src0.cond_swizzle_z]; swizzle += f[src0.cond_swizzle_z];
swizzle += f[src0.cond_swizzle_w]; swizzle += f[src0.cond_swizzle_w];
if (swizzle == "xxxx") swizzle = "x"; if (swizzle == ".xxxx") swizzle = ".x";
if (swizzle == "yyyy") swizzle = "y"; else if (swizzle == ".yyyy") swizzle = ".y";
if (swizzle == "zzzz") swizzle = "z"; else if (swizzle == ".zzzz") swizzle = ".z";
if (swizzle == "wwww") swizzle = "w"; else if (swizzle == ".wwww") swizzle = ".w";
swizzle = swizzle == "xyzw" ? "" : "." + swizzle; if (swizzle == ".xyzw"sv)
{
swizzle.clear();
}
if (src0.exec_if_gr && src0.exec_if_eq) if (src0.exec_if_gr && src0.exec_if_eq)
{ {
@ -170,15 +174,14 @@ template<typename T> std::string CgBinaryDisasm::GetSrcDisAsm(T src)
"TEX6", "TEX7", "TEX8", "TEX9", "SSA" "TEX6", "TEX7", "TEX8", "TEX9", "SSA"
}; };
const std::string perspective_correction = src2.perspective_corr ? "g" : "f";
const std::string input_attr_reg = reg_table[dst.src_attr_reg_num];
switch (dst.src_attr_reg_num) switch (dst.src_attr_reg_num)
{ {
case 0x00: ret += reg_table[0]; break; case 0x00: ret += reg_table[0]; break;
default: default:
if (dst.src_attr_reg_num < std::size(reg_table)) if (dst.src_attr_reg_num < std::size(reg_table))
{ {
const std::string perspective_correction = src2.perspective_corr ? "g" : "f";
const std::string input_attr_reg = reg_table[dst.src_attr_reg_num];
ret += fmt::format("%s[%s]", perspective_correction.c_str(), input_attr_reg.c_str()); ret += fmt::format("%s[%s]", perspective_correction.c_str(), input_attr_reg.c_str());
} }
else else
@ -199,20 +202,25 @@ template<typename T> std::string CgBinaryDisasm::GetSrcDisAsm(T src)
break; break;
} }
static const char f[4] = { 'x', 'y', 'z', 'w' }; static constexpr std::string_view f = "xyzw";
std::string swizzle; std::string swizzle;
swizzle.reserve(5);
swizzle += '.';
swizzle += f[src.swizzle_x]; swizzle += f[src.swizzle_x];
swizzle += f[src.swizzle_y]; swizzle += f[src.swizzle_y];
swizzle += f[src.swizzle_z]; swizzle += f[src.swizzle_z];
swizzle += f[src.swizzle_w]; swizzle += f[src.swizzle_w];
if (swizzle == "xxxx") swizzle = "x"; if (swizzle == ".xxxx") swizzle = ".x";
if (swizzle == "yyyy") swizzle = "y"; else if (swizzle == ".yyyy") swizzle = ".y";
if (swizzle == "zzzz") swizzle = "z"; else if (swizzle == ".zzzz") swizzle = ".z";
if (swizzle == "wwww") swizzle = "w"; else if (swizzle == ".wwww") swizzle = ".w";
if (strncmp(swizzle.c_str(), f, 4) != 0) ret += "." + swizzle; if (swizzle != ".xyzw"sv)
{
ret += swizzle;
}
if (src.neg) ret = "-" + ret; if (src.neg) ret = "-" + ret;
if (src.abs) ret = "|" + ret + "|"; if (src.abs) ret = "|" + ret + "|";

View file

@ -19,6 +19,8 @@ void CgBinaryDisasm::AddVecCodeDisasm(const std::string& code)
std::string CgBinaryDisasm::GetMaskDisasm(bool is_sca) std::string CgBinaryDisasm::GetMaskDisasm(bool is_sca)
{ {
std::string ret; std::string ret;
ret.reserve(5);
ret += '.';
if (is_sca) if (is_sca)
{ {
@ -35,7 +37,7 @@ std::string CgBinaryDisasm::GetMaskDisasm(bool is_sca)
if (d3.vec_writemask_w) ret += "w"; if (d3.vec_writemask_w) ret += "w";
} }
return ret.empty() || ret == "xyzw" ? "" : ("." + ret); return ret == "."sv || ret == ".xyzw"sv ? "" : (ret);
} }
std::string CgBinaryDisasm::GetVecMaskDisasm() std::string CgBinaryDisasm::GetVecMaskDisasm()
@ -103,21 +105,25 @@ std::string CgBinaryDisasm::GetSRCDisasm(const u32 n)
break; break;
} }
static const std::string f = "xyzw"; static constexpr std::string_view f = "xyzw";
std::string swizzle; std::string swizzle;
swizzle.reserve(5);
swizzle += '.';
swizzle += f[src[n].swz_x]; swizzle += f[src[n].swz_x];
swizzle += f[src[n].swz_y]; swizzle += f[src[n].swz_y];
swizzle += f[src[n].swz_z]; swizzle += f[src[n].swz_z];
swizzle += f[src[n].swz_w]; swizzle += f[src[n].swz_w];
if (swizzle == "xxxx") swizzle = "x"; if (swizzle == ".xxxx") swizzle = ".x";
if (swizzle == "yyyy") swizzle = "y"; else if (swizzle == ".yyyy") swizzle = ".y";
if (swizzle == "zzzz") swizzle = "z"; else if (swizzle == ".zzzz") swizzle = ".z";
if (swizzle == "wwww") swizzle = "w"; else if (swizzle == ".wwww") swizzle = ".w";
if (swizzle != f) ret += '.' + swizzle; if (swizzle != ".xyzw"sv)
{
ret += swizzle;
}
bool abs = false; bool abs = false;
@ -221,20 +227,25 @@ std::string CgBinaryDisasm::GetCondDisasm()
"ERROR" "ERROR"
}; };
static const char f[4] = { 'x', 'y', 'z', 'w' }; static constexpr std::string_view f = "xyzw";
std::string swizzle; std::string swizzle;
swizzle.reserve(5);
swizzle += '.';
swizzle += f[d0.mask_x]; swizzle += f[d0.mask_x];
swizzle += f[d0.mask_y]; swizzle += f[d0.mask_y];
swizzle += f[d0.mask_z]; swizzle += f[d0.mask_z];
swizzle += f[d0.mask_w]; swizzle += f[d0.mask_w];
if (swizzle == "xxxx") swizzle = "x"; if (swizzle == ".xxxx") swizzle = ".x";
if (swizzle == "yyyy") swizzle = "y"; else if (swizzle == ".yyyy") swizzle = ".y";
if (swizzle == "zzzz") swizzle = "z"; else if (swizzle == ".zzzz") swizzle = ".z";
if (swizzle == "wwww") swizzle = "w"; else if (swizzle == ".wwww") swizzle = ".w";
swizzle = swizzle == "xyzw" ? "" : "." + swizzle; if (swizzle == ".xyzw"sv)
{
swizzle.clear();
}
return fmt::format("(%s%s)", cond_string_table[d0.cond], swizzle.c_str()); return fmt::format("(%s%s)", cond_string_table[d0.cond], swizzle.c_str());
} }
@ -268,20 +279,25 @@ void CgBinaryDisasm::AddCodeCondDisasm(const std::string& dst, const std::string
"ERROR" "ERROR"
}; };
static const char f[4] = { 'x', 'y', 'z', 'w' }; static constexpr std::string_view f = "xyzw";
std::string swizzle; std::string swizzle;
swizzle.reserve(5);
swizzle += '.';
swizzle += f[d0.mask_x]; swizzle += f[d0.mask_x];
swizzle += f[d0.mask_y]; swizzle += f[d0.mask_y];
swizzle += f[d0.mask_z]; swizzle += f[d0.mask_z];
swizzle += f[d0.mask_w]; swizzle += f[d0.mask_w];
if (swizzle == "xxxx") swizzle = "x"; if (swizzle == ".xxxx") swizzle = ".x";
if (swizzle == "yyyy") swizzle = "y"; else if (swizzle == ".yyyy") swizzle = ".y";
if (swizzle == "zzzz") swizzle = "z"; else if (swizzle == ".zzzz") swizzle = ".z";
if (swizzle == "wwww") swizzle = "w"; else if (swizzle == ".wwww") swizzle = ".w";
swizzle = swizzle == "xyzw" ? "" : "." + swizzle; if (swizzle == ".xyzw"sv)
{
swizzle.clear();
}
std::string cond = fmt::format("%s%s", cond_string_table[d0.cond], swizzle.c_str()); std::string cond = fmt::format("%s%s", cond_string_table[d0.cond], swizzle.c_str());
AddCodeDisasm(dst + "(" + cond + ") " + ", " + src + ";"); AddCodeDisasm(dst + "(" + cond + ") " + ", " + src + ";");
@ -290,13 +306,13 @@ void CgBinaryDisasm::AddCodeCondDisasm(const std::string& dst, const std::string
std::string CgBinaryDisasm::AddAddrMaskDisasm() std::string CgBinaryDisasm::AddAddrMaskDisasm()
{ {
static const char f[] = { 'x', 'y', 'z', 'w' }; static constexpr std::string_view f = "xyzw";
return std::string(".") + f[d0.addr_swz]; return std::string(".") + f[d0.addr_swz];
} }
std::string CgBinaryDisasm::AddAddrRegDisasm() std::string CgBinaryDisasm::AddAddrRegDisasm()
{ {
static const char f[] = { 'x', 'y', 'z', 'w' }; //static constexpr std::string_view f = "xyzw";
return fmt::format("A%d", d0.addr_reg_sel_1) + AddAddrMaskDisasm(); return fmt::format("A%d", d0.addr_reg_sel_1) + AddAddrMaskDisasm();
} }

View file

@ -173,18 +173,17 @@ void FragmentProgramDecompiler::AddCode(const std::string& code)
std::string FragmentProgramDecompiler::GetMask() std::string FragmentProgramDecompiler::GetMask()
{ {
std::string ret; std::string ret;
ret.reserve(5);
static const char dst_mask[4] = static constexpr std::string_view dst_mask = "xyzw";
{
'x', 'y', 'z', 'w',
};
ret += '.';
if (dst.mask_x) ret += dst_mask[0]; if (dst.mask_x) ret += dst_mask[0];
if (dst.mask_y) ret += dst_mask[1]; if (dst.mask_y) ret += dst_mask[1];
if (dst.mask_z) ret += dst_mask[2]; if (dst.mask_z) ret += dst_mask[2];
if (dst.mask_w) ret += dst_mask[3]; if (dst.mask_w) ret += dst_mask[3];
return ret.empty() || strncmp(ret.c_str(), dst_mask, 4) == 0 ? "" : ("." + ret); return ret == "."sv || ret == ".xyzw"sv ? "" : (ret);
} }
std::string FragmentProgramDecompiler::AddReg(u32 index, bool fp16) std::string FragmentProgramDecompiler::AddReg(u32 index, bool fp16)
@ -366,14 +365,20 @@ std::string FragmentProgramDecompiler::Format(const std::string& code, bool igno
std::string FragmentProgramDecompiler::GetRawCond() std::string FragmentProgramDecompiler::GetRawCond()
{ {
static const char f[4] = { 'x', 'y', 'z', 'w' }; static constexpr std::string_view f = "xyzw";
std::string swizzle, cond; std::string swizzle, cond;
swizzle.reserve(5);
swizzle += '.';
swizzle += f[src0.cond_swizzle_x]; swizzle += f[src0.cond_swizzle_x];
swizzle += f[src0.cond_swizzle_y]; swizzle += f[src0.cond_swizzle_y];
swizzle += f[src0.cond_swizzle_z]; swizzle += f[src0.cond_swizzle_z];
swizzle += f[src0.cond_swizzle_w]; swizzle += f[src0.cond_swizzle_w];
swizzle = swizzle == "xyzw" ? "" : "." + swizzle;
if (swizzle == ".xyzw"sv)
{
swizzle.clear();
}
if (src0.exec_if_gr && src0.exec_if_eq) if (src0.exec_if_gr && src0.exec_if_eq)
cond = compareFunction(COMPARE::FUNCTION_SGE, AddCond() + swizzle, getFloatTypeName(4) + "(0., 0., 0., 0.)"); cond = compareFunction(COMPARE::FUNCTION_SGE, AddCond() + swizzle, getFloatTypeName(4) + "(0., 0., 0., 0.)");
@ -663,15 +668,20 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
break; break;
} }
static const char f[4] = { 'x', 'y', 'z', 'w' }; static constexpr std::string_view f = "xyzw";
std::string swizzle; std::string swizzle;
swizzle.reserve(5);
swizzle += '.';
swizzle += f[src.swizzle_x]; swizzle += f[src.swizzle_x];
swizzle += f[src.swizzle_y]; swizzle += f[src.swizzle_y];
swizzle += f[src.swizzle_z]; swizzle += f[src.swizzle_z];
swizzle += f[src.swizzle_w]; swizzle += f[src.swizzle_w];
if (strncmp(swizzle.c_str(), f, 4) != 0) ret += "." + swizzle; if (swizzle != ".xyzw"sv)
{
ret += swizzle;
}
// Warning: Modifier order matters. e.g neg should be applied after precision clamping (tested with Naruto UNS) // Warning: Modifier order matters. e.g neg should be applied after precision clamping (tested with Naruto UNS)
if (src.abs) ret = "abs(" + ret + ")"; if (src.abs) ret = "abs(" + ret + ")";