mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 16:21:02 +00:00
rsx/fp: Improve rgister component gather detection
- Also avoids clobbering register data by keeping gathered bits in a temp var
This commit is contained in:
parent
87741141f1
commit
68b3229756
@ -111,7 +111,7 @@ void FragmentProgramDecompiler::SetDst(std::string code, bool append_mask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 reg_index = dst.fp16 ? dst.dest_reg >> 1 : dst.dest_reg;
|
u32 reg_index = dst.fp16 ? dst.dest_reg >> 1 : dst.dest_reg;
|
||||||
temp_registers[reg_index].tag(dst.dest_reg, !!dst.fp16);
|
temp_registers[reg_index].tag(dst.dest_reg, !!dst.fp16, dst.mask_x, dst.mask_y, dst.mask_z, dst.mask_w);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FragmentProgramDecompiler::AddFlowOp(std::string code)
|
void FragmentProgramDecompiler::AddFlowOp(std::string code)
|
||||||
@ -283,14 +283,15 @@ std::string FragmentProgramDecompiler::Format(const std::string& code, bool igno
|
|||||||
{ "$_i", [this]() -> std::string {return std::to_string(dst.tex_num);} },
|
{ "$_i", [this]() -> std::string {return std::to_string(dst.tex_num);} },
|
||||||
{ "$m", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetMask), this) },
|
{ "$m", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetMask), this) },
|
||||||
{ "$ifcond ", [this]() -> std::string
|
{ "$ifcond ", [this]() -> std::string
|
||||||
{
|
{
|
||||||
const std::string& cond = GetCond();
|
const std::string& cond = GetCond();
|
||||||
if (cond == "true") return "";
|
if (cond == "true") return "";
|
||||||
return "if(" + cond + ") ";
|
return "if(" + cond + ") ";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "$cond", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetCond), this) },
|
{ "$cond", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetCond), this) },
|
||||||
{ "$_c", std::bind(std::mem_fn(&FragmentProgramDecompiler::AddConst), this) }
|
{ "$_c", std::bind(std::mem_fn(&FragmentProgramDecompiler::AddConst), this) },
|
||||||
|
{ "$float4", [this]() -> std::string { return getFloatTypeName(4); } }
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!ignore_redirects)
|
if (!ignore_redirects)
|
||||||
@ -407,20 +408,13 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
|
|||||||
dst.opcode == RSX_FP_OPCODE_UPB ||
|
dst.opcode == RSX_FP_OPCODE_UPB ||
|
||||||
dst.opcode == RSX_FP_OPCODE_UPG)
|
dst.opcode == RSX_FP_OPCODE_UPG)
|
||||||
{
|
{
|
||||||
//TODO: Implement aliased gather for half floats
|
|
||||||
bool xy_read = false;
|
|
||||||
bool zw_read = false;
|
|
||||||
|
|
||||||
if (src.swizzle_x < 2 || src.swizzle_y < 2 || src.swizzle_z < 2 || src.swizzle_w < 2)
|
|
||||||
xy_read = true;
|
|
||||||
if (src.swizzle_x > 1 || src.swizzle_y > 1 || src.swizzle_z > 1 || src.swizzle_w > 1)
|
|
||||||
zw_read = true;
|
|
||||||
|
|
||||||
auto ® = temp_registers[src.tmp_reg_index];
|
auto ® = temp_registers[src.tmp_reg_index];
|
||||||
if (reg.requires_gather(xy_read, zw_read))
|
if (reg.requires_gather(src.swizzle_x))
|
||||||
{
|
{
|
||||||
properties.has_gather_op = true;
|
properties.has_gather_op = true;
|
||||||
AddCode(reg.gather_r());
|
AddReg(src.tmp_reg_index, src.fp16);
|
||||||
|
ret = getFloatTypeName(4) + reg.gather_r();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,25 +24,41 @@ class FragmentProgramDecompiler
|
|||||||
bool aliased_r0 = false;
|
bool aliased_r0 = false;
|
||||||
bool aliased_h0 = false;
|
bool aliased_h0 = false;
|
||||||
bool aliased_h1 = false;
|
bool aliased_h1 = false;
|
||||||
bool last_write_half = false;
|
bool last_write_half[4] = { false, false, false, false };
|
||||||
|
|
||||||
u32 real_index = UINT32_MAX;
|
u32 real_index = UINT32_MAX;
|
||||||
|
|
||||||
void tag(u32 index, bool half_register)
|
void tag(u32 index, bool half_register, bool x, bool y, bool z, bool w)
|
||||||
{
|
{
|
||||||
if (half_register)
|
if (half_register)
|
||||||
{
|
{
|
||||||
last_write_half = true;
|
|
||||||
|
|
||||||
if (index & 1)
|
if (index & 1)
|
||||||
|
{
|
||||||
|
if (x) last_write_half[2] = true;
|
||||||
|
if (y) last_write_half[2] = true;
|
||||||
|
if (z) last_write_half[3] = true;
|
||||||
|
if (w) last_write_half[3] = true;
|
||||||
|
|
||||||
aliased_h1 = true;
|
aliased_h1 = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (x) last_write_half[0] = true;
|
||||||
|
if (y) last_write_half[0] = true;
|
||||||
|
if (z) last_write_half[1] = true;
|
||||||
|
if (w) last_write_half[1] = true;
|
||||||
|
|
||||||
aliased_h0 = true;
|
aliased_h0 = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (x) last_write_half[0] = false;
|
||||||
|
if (y) last_write_half[1] = false;
|
||||||
|
if (z) last_write_half[2] = false;
|
||||||
|
if (w) last_write_half[3] = false;
|
||||||
|
|
||||||
aliased_r0 = true;
|
aliased_r0 = true;
|
||||||
last_write_half = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (real_index == UINT32_MAX)
|
if (real_index == UINT32_MAX)
|
||||||
@ -54,12 +70,19 @@ class FragmentProgramDecompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool requires_gather(bool xy, bool zw) const
|
bool requires_gather(u8 channel) const
|
||||||
{
|
{
|
||||||
//Data fetched from the single precision register requires merging of the two half registers
|
//Data fetched from the single precision register requires merging of the two half registers
|
||||||
//TODO: Check individual swizzle channels
|
verify(HERE), channel < 4;
|
||||||
if ((aliased_h0 && xy) || (aliased_h1 && zw))
|
if (aliased_h0 && channel < 2)
|
||||||
return last_write_half;
|
{
|
||||||
|
return last_write_half[channel];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aliased_h1 && channel > 1)
|
||||||
|
{
|
||||||
|
return last_write_half[channel];
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -67,7 +90,7 @@ class FragmentProgramDecompiler
|
|||||||
bool requires_split(u32 /*index*/) const
|
bool requires_split(u32 /*index*/) const
|
||||||
{
|
{
|
||||||
//Data fetched from any of the two half registers requires sync with the full register
|
//Data fetched from any of the two half registers requires sync with the full register
|
||||||
if (!last_write_half && aliased_r0)
|
if (!(last_write_half[0] || last_write_half[1]) && aliased_r0)
|
||||||
{
|
{
|
||||||
//r0 has been written to
|
//r0 has been written to
|
||||||
//TODO: Check for specific elements in real32 register
|
//TODO: Check for specific elements in real32 register
|
||||||
@ -85,15 +108,12 @@ class FragmentProgramDecompiler
|
|||||||
std::string ret = "//Invalid gather";
|
std::string ret = "//Invalid gather";
|
||||||
|
|
||||||
if (aliased_h0 && aliased_h1)
|
if (aliased_h0 && aliased_h1)
|
||||||
ret = reg + " = gather(" + h0 + ", " + h1 + ");";
|
ret = "(gather(" + h0 + ", " + h1 + "))";
|
||||||
else if (aliased_h0)
|
else if (aliased_h0)
|
||||||
ret = reg + ".xy = gather(" + h0 + ");";
|
ret = "(gather(" + h0 + "), " + reg + ".zw)";
|
||||||
else if (aliased_h1)
|
else if (aliased_h1)
|
||||||
ret = reg + ".zw = gather(" + h1 + ");";
|
ret = "(" + reg + ".xy, gather(" + h1 + "))";
|
||||||
|
|
||||||
last_write_half = false;
|
|
||||||
aliased_h0 = false;
|
|
||||||
aliased_h1 = false;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user