1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 18:53:28 +01:00

rsx: Implement point sprite coordinate generation

- When the point sprite flag is set, overrides the input similar to the
2D mask. The returned X and Y values are always the gl_PointCoord values
for the fragment.
- Stacks with the 2D mask to override the z and w coordinates.
This commit is contained in:
kd-11 2019-11-08 20:19:54 +03:00 committed by kd-11
parent 81c61e230f
commit 7072489a6e
5 changed files with 72 additions and 6 deletions

View File

@ -579,10 +579,24 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
case 0xD:
{
// TEX0 - TEX9
// Texcoord mask seems to reset the last 2 arguments to 0 and 1 if set
if (m_prog.texcoord_is_2d(dst.src_attr_reg_num - 4))
// Texcoord 2d mask seems to reset the last 2 arguments to 0 and w if set
const u8 texcoord = u8(dst.src_attr_reg_num) - 4;
if (m_prog.texcoord_is_point_coord(texcoord))
{
ret += getFloatTypeName(4) + "(" + reg_var + ".x, " + reg_var + ".y, 0., in_w)";
// Point sprite coord generation. Stacks with the 2D override mask.
if (m_prog.texcoord_is_2d(texcoord))
{
ret += getFloatTypeName(4) + "(gl_PointCoord, 0., in_w)";
properties.has_w_access = true;
}
else
{
ret += getFloatTypeName(4) + "(gl_PointCoord, 1., 0.)";
}
}
else if (m_prog.texcoord_is_2d(texcoord))
{
ret += getFloatTypeName(4) + "(" + reg_var + ".xy, 0., in_w)";
properties.has_w_access = true;
}
else

View File

@ -251,7 +251,13 @@ struct RSXFragmentProgram
bool texcoord_is_2d(u8 index) const
{
return !!(texcoord_control_mask & (1u << index));
return bool(texcoord_control_mask & (1u << index));
}
bool texcoord_is_point_coord(u8 index) const
{
index += 16;
return bool(texcoord_control_mask & (1u << index));
}
RSXFragmentProgram()

View File

@ -1698,6 +1698,13 @@ namespace rsx
result.redirected_textures = 0;
result.shadow_textures = 0;
if (method_registers.current_draw_clause.primitive == primitive_type::points &&
method_registers.point_sprite_enabled())
{
// Set high word of the control mask to store point sprite control
result.texcoord_control_mask |= u32(method_registers.point_sprite_control_mask()) << 16;
}
const auto resolution_scale = rsx::get_resolution_scale();
for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i)

View File

@ -3256,6 +3256,35 @@ struct registers_decoder<NV4097_SET_POINT_SIZE>
}
};
template<>
struct registers_decoder<NV4097_SET_POINT_SPRITE_CONTROL>
{
struct decoded_type
{
private:
u32 value;
public:
decoded_type(u32 value) : value(value) {}
bool enabled() const
{
return bf_decoder<0, 1, bool>(value);
}
u16 texcoord_mask() const
{
return bf_decoder<8, 10>(value);
}
};
static std::string dump(decoded_type &&decoded_values)
{
return "Point sprite: enabled = " + print_boolean(decoded_values.enabled()) +
"override mask = " + fmt::format("0x%x", decoded_values.texcoord_mask());
}
};
template<>
struct registers_decoder<NV4097_SET_SURFACE_FORMAT>
{

View File

@ -1102,6 +1102,11 @@ namespace rsx
return decode<NV4097_SET_POINT_SIZE>().point_size();
}
bool point_sprite_enabled() const
{
return decode<NV4097_SET_POINT_SPRITE_CONTROL>().enabled();
}
u8 alpha_ref() const
{
return decode<NV4097_SET_ALPHA_REF>().alpha_ref();
@ -1677,10 +1682,10 @@ namespace rsx
return decode<NV4097_SET_CONTROL0>().depth_float();
}
u32 texcoord_control_mask()
u16 texcoord_control_mask() const
{
// Only 10 texture coords exist [0-9]
u32 control_mask = 0;
u16 control_mask = 0;
for (u8 index = 0; index < 10; ++index)
{
control_mask |= ((registers[NV4097_SET_TEX_COORD_CONTROL + index] & 1) << index);
@ -1688,6 +1693,11 @@ namespace rsx
return control_mask;
}
u16 point_sprite_control_mask() const
{
return decode<NV4097_SET_POINT_SPRITE_CONTROL>().texcoord_mask();
}
};
extern rsx_state method_registers;