rsx/fp: Support more types of texture access

- Allows more instructions to correctly decode depth textures
This commit is contained in:
kd-11
2020-05-12 23:52:11 +03:00
committed by kd-11
parent 7680466e0d
commit ed82288c1b
3 changed files with 103 additions and 100 deletions
@@ -938,6 +938,34 @@ bool FragmentProgramDecompiler::handle_sct_scb(u32 opcode)
bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode) bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
{ {
auto insert_texture_fetch = [this](const std::array<FUNCTION, 6>& functions)
{
const auto type = m_prog.get_texture_dimension(dst.tex_num);
std::string mask = "";
auto select = static_cast<u8>(type);
if (type == rsx::texture_dimension_extended::texture_dimension_2d)
{
if (m_prog.shadow_textures & (1 << dst.tex_num))
{
m_shadow_sampled_textures |= (1 << dst.tex_num);
select = 4;
mask = ".xxxx";
}
else
{
m_2d_sampled_textures |= (1 << dst.tex_num);
if (m_prog.redirected_textures & (1 << dst.tex_num))
{
select = 5;
}
}
}
auto function = functions[select];
SetDst(getFunction(function) + mask);
};
switch (opcode) switch (opcode)
{ {
case RSX_FP_OPCODE_DDX: SetDst(getFunction(FUNCTION::FUNCTION_DFDX)); return true; case RSX_FP_OPCODE_DDX: SetDst(getFunction(FUNCTION::FUNCTION_DFDX)); return true;
@@ -945,125 +973,97 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_NRM: SetDst("_builtin_normalize($0.xyz).xyzz", OPFLAGS::src_cast_f32); return true; case RSX_FP_OPCODE_NRM: SetDst("_builtin_normalize($0.xyz).xyzz", OPFLAGS::src_cast_f32); return true;
case RSX_FP_OPCODE_BEM: SetDst("$0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw"); return true; case RSX_FP_OPCODE_BEM: SetDst("$0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw"); return true;
case RSX_FP_OPCODE_TEXBEM: case RSX_FP_OPCODE_TEXBEM:
{
//Untested, should be x2d followed by TEX //Untested, should be x2d followed by TEX
AddX2d(); AddX2d();
AddCode(Format("x2d = $0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw;", true)); AddCode(Format("x2d = $0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw;", true));
[[fallthrough]]; [[fallthrough]];
}
case RSX_FP_OPCODE_TEX: case RSX_FP_OPCODE_TEX:
{
AddTex(); AddTex();
switch (m_prog.get_texture_dimension(dst.tex_num)) insert_texture_fetch({
{ FUNCTION::FUNCTION_TEXTURE_SAMPLE1D,
case rsx::texture_dimension_extended::texture_dimension_1d: FUNCTION::FUNCTION_TEXTURE_SAMPLE2D,
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D)); FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE,
return true; FUNCTION::FUNCTION_TEXTURE_SAMPLE3D,
case rsx::texture_dimension_extended::texture_dimension_2d: FUNCTION::FUNCTION_TEXTURE_SHADOW2D,
if (m_prog.shadow_textures & (1 << dst.tex_num)) FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA
{ });
m_shadow_sampled_textures |= (1 << dst.tex_num);
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SHADOW2D) + ".xxxx"); return true;
return true; }
}
if (m_prog.redirected_textures & (1 << dst.tex_num))
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA));
else
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D));
m_2d_sampled_textures |= (1 << dst.tex_num);
return true;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE));
return true;
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D));
return true;
}
return false;
case RSX_FP_OPCODE_TXPBEM: case RSX_FP_OPCODE_TXPBEM:
//Untested, should be x2d followed by TXP {
// Untested, should be x2d followed by TXP
AddX2d(); AddX2d();
AddCode(Format("x2d = $0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw;", true)); AddCode(Format("x2d = $0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw;", true));
[[fallthrough]]; [[fallthrough]];
}
case RSX_FP_OPCODE_TXP: case RSX_FP_OPCODE_TXP:
{
AddTex(); AddTex();
switch (m_prog.get_texture_dimension(dst.tex_num)) insert_texture_fetch({
{ FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ,
case rsx::texture_dimension_extended::texture_dimension_1d: FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ,
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ)); FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ,
return true; FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ,
case rsx::texture_dimension_extended::texture_dimension_2d: FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ,
//Note shadow comparison only returns a true/false result! FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA_PROJ
if (m_prog.shadow_textures & (1 << dst.tex_num)) });
{
m_shadow_sampled_textures |= (1 << dst.tex_num); return true;
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ) + ".xxxx"); }
}
else
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ));
return true;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ));
return true;
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ));
return true;
}
return false;
case RSX_FP_OPCODE_TXD: case RSX_FP_OPCODE_TXD:
{
AddTex(); AddTex();
switch (m_prog.get_texture_dimension(dst.tex_num))
if (m_prog.redirected_textures & (1 << dst.tex_num) ||
m_prog.shadow_textures & (1 << dst.tex_num))
{ {
case rsx::texture_dimension_extended::texture_dimension_1d: // Doesn't make sense to sample with derivates for these types
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD)); rsx_log.error("[Unimplemented warning] TXD operation performed on shadow/redirected texture!");
return true;
case rsx::texture_dimension_extended::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD));
m_2d_sampled_textures |= (1 << dst.tex_num);
return true;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD));
return true;
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD));
return true;
} }
return false;
insert_texture_fetch({
FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD,
FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD,
FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD,
FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD,
FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD,
FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD
});
return true;
}
case RSX_FP_OPCODE_TXB: case RSX_FP_OPCODE_TXB:
{
AddTex(); AddTex();
switch (m_prog.get_texture_dimension(dst.tex_num)) insert_texture_fetch({
{ FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_BIAS,
case rsx::texture_dimension_extended::texture_dimension_1d: FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_BIAS,
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_BIAS)); FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_BIAS,
return true; FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_BIAS,
case rsx::texture_dimension_extended::texture_dimension_2d: FUNCTION::FUNCTION_TEXTURE_SHADOW2D, // Shadow and depth_rgba variants are generated for framebuffers where only LOD0 exists
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_BIAS)); FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA
m_2d_sampled_textures |= (1 << dst.tex_num); });
return true;
case rsx::texture_dimension_extended::texture_dimension_cubemap: return true;
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_BIAS)); }
return true;
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_BIAS));
return true;
}
return false;
case RSX_FP_OPCODE_TXL: case RSX_FP_OPCODE_TXL:
{
AddTex(); AddTex();
switch (m_prog.get_texture_dimension(dst.tex_num)) insert_texture_fetch({
{ FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD,
case rsx::texture_dimension_extended::texture_dimension_1d: FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD,
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD)); FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD,
return true; FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD,
case rsx::texture_dimension_extended::texture_dimension_2d: FUNCTION::FUNCTION_TEXTURE_SHADOW2D, // Shadow and depth_rgba variants are generated for framebuffers where only LOD0 exists
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD)); FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA
m_2d_sampled_textures |= (1 << dst.tex_num); });
return true;
case rsx::texture_dimension_extended::texture_dimension_cubemap: return true;
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD)); }
return true;
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD));
return true;
}
return false;
// Unpack operations. See https://www.khronos.org/registry/OpenGL/extensions/NV/NV_fragment_program.txt // Unpack operations. See https://www.khronos.org/registry/OpenGL/extensions/NV/NV_fragment_program.txt
// UP2 = UP2H (2 16-bit floats) // UP2 = UP2H (2 16-bit floats)
// UP16 = UP2US (2 unsigned 16-bit scalars) // UP16 = UP2US (2 unsigned 16-bit scalars)
+2
View File
@@ -876,6 +876,8 @@ namespace glsl
return "textureLod($t, $0.xyz, 0)"; return "textureLod($t, $0.xyz, 0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA: case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
return "TEX2D_DEPTH_RGBA8($_i, $0.xy)"; return "TEX2D_DEPTH_RGBA8($_i, $0.xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA_PROJ:
return "TEX2D_DEPTH_RGBA8($_i, ($0.xy / $0.w))";
} }
} }
+2 -1
View File
@@ -45,7 +45,8 @@ enum class FUNCTION
FUNCTION_VERTEX_TEXTURE_FETCH2D, FUNCTION_VERTEX_TEXTURE_FETCH2D,
FUNCTION_VERTEX_TEXTURE_FETCH3D, FUNCTION_VERTEX_TEXTURE_FETCH3D,
FUNCTION_VERTEX_TEXTURE_FETCHCUBE, FUNCTION_VERTEX_TEXTURE_FETCHCUBE,
FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA,
FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA_PROJ
}; };
enum class COMPARE enum class COMPARE