yuzu-emu
/
yuzu-android
Archived
1
0
Fork 0

glasm: Fix potential aliasing bug on cube array samples

This commit is contained in:
ReinUsesLisp 2021-05-20 15:58:39 -03:00 committed by ameerj
parent 8fdb00a2b5
commit 0a54291c9c
2 changed files with 44 additions and 35 deletions

View File

@ -268,9 +268,16 @@ void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu
} }
void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
const IR::Value& coord, ScalarF32 dref, Register bias_lc, const IR::Value& coord, const IR::Value& dref,
const IR::Value& offset) { const IR::Value& bias_lc, const IR::Value& offset) {
// Allocate early to avoid aliases
const auto info{inst.Flags<IR::TextureInstInfo>()}; const auto info{inst.Flags<IR::TextureInstInfo>()};
ScopedRegister staging;
if (info.type == TextureType::ColorArrayCube) {
staging = ScopedRegister{ctx.reg_alloc};
}
const ScalarF32 dref_val{ctx.reg_alloc.Consume(dref)};
const Register bias_lc_vec{ctx.reg_alloc.Consume(bias_lc)};
const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""};
const std::string_view type{TextureType(info)}; const std::string_view type{TextureType(info)};
@ -287,14 +294,14 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::
ctx.Add("MOV.F {}.z,{};" ctx.Add("MOV.F {}.z,{};"
"MOV.F {}.w,{}.x;" "MOV.F {}.w,{}.x;"
"TXB.F.LODCLAMP{} {},{},{}.y,{},{}{};", "TXB.F.LODCLAMP{} {},{},{}.y,{},{}{};",
coord_vec, dref, coord_vec, bias_lc, sparse_mod, ret, coord_vec, bias_lc, coord_vec, dref_val, coord_vec, bias_lc_vec, sparse_mod, ret, coord_vec,
texture, type, offset_vec); bias_lc_vec, texture, type, offset_vec);
break; break;
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
case TextureType::ColorCube: case TextureType::ColorCube:
ctx.Add("MOV.F {}.w,{};" ctx.Add("MOV.F {}.w,{};"
"TXB.F.LODCLAMP{} {},{},{},{},{}{};", "TXB.F.LODCLAMP{} {},{},{},{},{}{};",
coord_vec, dref, sparse_mod, ret, coord_vec, bias_lc, texture, type, coord_vec, dref_val, sparse_mod, ret, coord_vec, bias_lc_vec, texture, type,
offset_vec); offset_vec);
break; break;
default: default:
@ -309,25 +316,23 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::
ctx.Add("MOV.F {}.z,{};" ctx.Add("MOV.F {}.z,{};"
"MOV.F {}.w,{}.x;" "MOV.F {}.w,{}.x;"
"TXB.F{} {},{},{},{}{};", "TXB.F{} {},{},{},{}{};",
coord_vec, dref, coord_vec, bias_lc, sparse_mod, ret, coord_vec, texture, coord_vec, dref_val, coord_vec, bias_lc_vec, sparse_mod, ret, coord_vec,
type, offset_vec); texture, type, offset_vec);
break; break;
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
case TextureType::ColorCube: case TextureType::ColorCube:
ctx.Add("MOV.F {}.w,{};" ctx.Add("MOV.F {}.w,{};"
"TXB.F{} {},{},{},{},{}{};", "TXB.F{} {},{},{},{},{}{};",
coord_vec, dref, sparse_mod, ret, coord_vec, bias_lc, texture, type, coord_vec, dref_val, sparse_mod, ret, coord_vec, bias_lc_vec, texture, type,
offset_vec); offset_vec);
break; break;
case TextureType::ColorArrayCube: { case TextureType::ColorArrayCube:
const ScopedRegister pair{ctx.reg_alloc};
ctx.Add("MOV.F {}.x,{};" ctx.Add("MOV.F {}.x,{};"
"MOV.F {}.y,{}.x;" "MOV.F {}.y,{}.x;"
"TXB.F{} {},{},{},{},{}{};", "TXB.F{} {},{},{},{},{}{};",
pair.reg, dref, pair.reg, bias_lc, sparse_mod, ret, coord_vec, pair.reg, staging.reg, dref_val, staging.reg, bias_lc_vec, sparse_mod, ret, coord_vec,
texture, type, offset_vec); staging.reg, texture, type, offset_vec);
break; break;
}
default: default:
throw NotImplementedException("Invalid type {}", info.type.Value()); throw NotImplementedException("Invalid type {}", info.type.Value());
} }
@ -340,15 +345,14 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::
const char dref_swizzle{w_swizzle ? 'w' : 'z'}; const char dref_swizzle{w_swizzle ? 'w' : 'z'};
ctx.Add("MOV.F {}.{},{};" ctx.Add("MOV.F {}.{},{};"
"TEX.F.LODCLAMP{} {},{},{},{},{}{};", "TEX.F.LODCLAMP{} {},{},{},{},{}{};",
coord_vec, dref_swizzle, dref, sparse_mod, ret, coord_vec, bias_lc, texture, coord_vec, dref_swizzle, dref_val, sparse_mod, ret, coord_vec, bias_lc_vec,
type, offset_vec); texture, type, offset_vec);
} else { } else {
const ScopedRegister pair{ctx.reg_alloc};
ctx.Add("MOV.F {}.x,{};" ctx.Add("MOV.F {}.x,{};"
"MOV.F {}.y,{};" "MOV.F {}.y,{};"
"TEX.F.LODCLAMP{} {},{},{},{},{}{};", "TEX.F.LODCLAMP{} {},{},{},{},{}{};",
pair.reg, dref, pair.reg, bias_lc, sparse_mod, ret, coord_vec, pair.reg, staging.reg, dref_val, staging.reg, bias_lc_vec, sparse_mod, ret, coord_vec,
texture, type, offset_vec); staging.reg, texture, type, offset_vec);
} }
} else { } else {
if (info.type != TextureType::ColorArrayCube) { if (info.type != TextureType::ColorArrayCube) {
@ -357,11 +361,10 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::
const char dref_swizzle{w_swizzle ? 'w' : 'z'}; const char dref_swizzle{w_swizzle ? 'w' : 'z'};
ctx.Add("MOV.F {}.{},{};" ctx.Add("MOV.F {}.{},{};"
"TEX.F{} {},{},{},{}{};", "TEX.F{} {},{},{},{}{};",
coord_vec, dref_swizzle, dref, sparse_mod, ret, coord_vec, texture, type, coord_vec, dref_swizzle, dref_val, sparse_mod, ret, coord_vec, texture,
offset_vec); type, offset_vec);
} else { } else {
const ScopedRegister pair{ctx.reg_alloc}; ctx.Add("TEX.F{} {},{},{},{},{}{};", sparse_mod, ret, coord_vec, dref_val, texture,
ctx.Add("TEX.F{} {},{},{},{},{}{};", sparse_mod, ret, coord_vec, dref, texture,
type, offset_vec); type, offset_vec);
} }
} }
@ -370,9 +373,16 @@ void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::
} }
void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
const IR::Value& coord, ScalarF32 dref, ScalarF32 lod, const IR::Value& coord, const IR::Value& dref,
const IR::Value& offset) { const IR::Value& lod, const IR::Value& offset) {
// Allocate early to avoid aliases
const auto info{inst.Flags<IR::TextureInstInfo>()}; const auto info{inst.Flags<IR::TextureInstInfo>()};
ScopedRegister staging;
if (info.type == TextureType::ColorArrayCube) {
staging = ScopedRegister{ctx.reg_alloc};
}
const ScalarF32 dref_val{ctx.reg_alloc.Consume(dref)};
const ScalarF32 lod_val{ctx.reg_alloc.Consume(lod)};
const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)}; const auto sparse_inst{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""};
const std::string_view type{TextureType(info)}; const std::string_view type{TextureType(info)};
@ -387,24 +397,23 @@ void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::
ctx.Add("MOV.F {}.z,{};" ctx.Add("MOV.F {}.z,{};"
"MOV.F {}.w,{};" "MOV.F {}.w,{};"
"TXL.F{} {},{},{},{}{};", "TXL.F{} {},{},{},{}{};",
coord_vec, dref, coord_vec, lod, sparse_mod, ret, coord_vec, texture, type, coord_vec, dref_val, coord_vec, lod_val, sparse_mod, ret, coord_vec, texture, type,
offset_vec); offset_vec);
break; break;
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
case TextureType::ColorCube: case TextureType::ColorCube:
ctx.Add("MOV.F {}.w,{};" ctx.Add("MOV.F {}.w,{};"
"TXL.F{} {},{},{},{},{}{};", "TXL.F{} {},{},{},{},{}{};",
coord_vec, dref, sparse_mod, ret, coord_vec, lod, texture, type, offset_vec); coord_vec, dref_val, sparse_mod, ret, coord_vec, lod_val, texture, type,
offset_vec);
break; break;
case TextureType::ColorArrayCube: { case TextureType::ColorArrayCube:
const ScopedRegister pair{ctx.reg_alloc};
ctx.Add("MOV.F {}.x,{};" ctx.Add("MOV.F {}.x,{};"
"MOV.F {}.y,{};" "MOV.F {}.y,{};"
"TXL.F{} {},{},{},{},{}{};", "TXL.F{} {},{},{},{},{}{};",
pair.reg, dref, pair.reg, lod, sparse_mod, ret, coord_vec, pair.reg, texture, type, staging.reg, dref_val, staging.reg, lod_val, sparse_mod, ret, coord_vec,
offset_vec); staging.reg, texture, type, offset_vec);
break; break;
}
default: default:
throw NotImplementedException("Invalid type {}", info.type.Value()); throw NotImplementedException("Invalid type {}", info.type.Value());
} }

View File

@ -533,11 +533,11 @@ void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Valu
void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
const IR::Value& coord, ScalarF32 lod, const IR::Value& offset); const IR::Value& coord, ScalarF32 lod, const IR::Value& offset);
void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
const IR::Value& coord, ScalarF32 dref, Register bias_lc, const IR::Value& coord, const IR::Value& dref,
const IR::Value& offset); const IR::Value& bias_lc, const IR::Value& offset);
void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
const IR::Value& coord, ScalarF32 dref, ScalarF32 lod, const IR::Value& coord, const IR::Value& dref,
const IR::Value& offset); const IR::Value& lod, const IR::Value& offset);
void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2); const IR::Value& coord, const IR::Value& offset, const IR::Value& offset2);
void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,