mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 14:08:37 +00:00
rsx/vk: Rework MSAA implementation
This commit is contained in:
parent
9c5ed01130
commit
bc7ed8eaab
30 changed files with 285 additions and 123 deletions
|
|
@ -1101,9 +1101,19 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
|
|||
|
||||
ensure(func_id <= FUNCTION::TEXTURE_SAMPLE_MAX_BASE_ENUM && func_id >= FUNCTION::TEXTURE_SAMPLE_BASE);
|
||||
|
||||
// Clamp type to 3 types (1d, 2d, cube+3d) and offset into sampling redirection table
|
||||
const auto type_offset = (std::min(static_cast<int>(type), 2) + 1) * static_cast<int>(FUNCTION::TEXTURE_SAMPLE_BASE_ENUM_COUNT);
|
||||
func_id = static_cast<FUNCTION>(static_cast<int>(func_id) + type_offset);
|
||||
if (!(m_prog.texture_state.multisampled_textures & ref_mask)) [[ likely ]]
|
||||
{
|
||||
// Clamp type to 3 types (1d, 2d, cube+3d) and offset into sampling redirection table
|
||||
const auto type_offset = (std::min(static_cast<int>(type), 2) + 1) * static_cast<int>(FUNCTION::TEXTURE_SAMPLE_BASE_ENUM_COUNT);
|
||||
func_id = static_cast<FUNCTION>(static_cast<int>(func_id) + type_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Map to multisample op
|
||||
ensure(type <= rsx::texture_dimension_extended::texture_dimension_2d);
|
||||
properties.multisampled_sampler_mask |= ref_mask;
|
||||
func_id = static_cast<FUNCTION>(static_cast<int>(func_id) - static_cast<int>(FUNCTION::TEXTURE_SAMPLE_BASE) + static_cast<int>(FUNCTION::TEXTURE_SAMPLE2DMS));
|
||||
}
|
||||
|
||||
if (dst.exp_tex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ public:
|
|||
u16 common_access_sampler_mask = 0;
|
||||
u16 shadow_sampler_mask = 0;
|
||||
u16 redirected_sampler_mask = 0;
|
||||
u16 multisampled_sampler_mask = 0;
|
||||
|
||||
bool has_lit_op = false;
|
||||
bool has_gather_op = false;
|
||||
|
|
|
|||
|
|
@ -591,7 +591,10 @@ namespace glsl
|
|||
|
||||
"#define ALPHAKILL " << rsx::texture_control_bits::ALPHAKILL << "\n"
|
||||
"#define RENORMALIZE " << rsx::texture_control_bits::RENORMALIZE << "\n"
|
||||
"#define DEPTH_FLOAT " << rsx::texture_control_bits::DEPTH_FLOAT << "\n"
|
||||
"#define DEPTH_FLOAT " << rsx::texture_control_bits::DEPTH_FLOAT << "\n"
|
||||
"#define DEPTH_COMPARE " << rsx::texture_control_bits::DEPTH_COMPARE_OP << "\n"
|
||||
"#define FILTERED_BIT " << rsx::texture_control_bits::FILTERED << "\n"
|
||||
"#define INT_COORDS_BIT " << rsx::texture_control_bits::UNNORMALIZED_COORDS << "\n"
|
||||
"#define GAMMA_CTRL_MASK (GAMMA_R_MASK|GAMMA_G_MASK|GAMMA_B_MASK|GAMMA_A_MASK)\n"
|
||||
"#define SIGN_EXPAND_MASK (EXPAND_R_MASK|EXPAND_G_MASK|EXPAND_B_MASK|EXPAND_A_MASK)\n\n";
|
||||
}
|
||||
|
|
@ -887,6 +890,40 @@ namespace glsl
|
|||
"#define TEX2D_Z24X8_RGBA8(index, coord2) process_texel(convert_z24x8_to_rgba8(ZS_READ(index, COORD_SCALE2(index, coord2)), texture_parameters[index].remap, TEX_FLAGS(index)), TEX_FLAGS(index))\n"
|
||||
"#define TEX3D_Z24X8_RGBA8(index, coord3) process_texel(convert_z24x8_to_rgba8(ZS_READ(index, COORD_SCALE3(index, coord3)), texture_parameters[index].remap, TEX_FLAGS(index)), TEX_FLAGS(index))\n\n";
|
||||
}
|
||||
|
||||
if (props.require_msaa_ops)
|
||||
{
|
||||
OS <<
|
||||
"#define ZCOMPARE_FUNC(index) _get_bits(TEX_FLAGS(index), DEPTH_COMPARE, 3)\n"
|
||||
"#define ZS_READ_MS(index, coord) vec2(sampleTexture2DMS(TEX_NAME(index), coord, index).r, float(sampleTexture2DMS(TEX_NAME_STENCIL(index), coord, index).x))\n"
|
||||
"#define TEX2D_MS(index, coord2) process_texel(sampleTexture2DMS(TEX_NAME(index), coord2, index), TEX_FLAGS(index))\n"
|
||||
"#define TEX2D_SHADOW_MS(index, coord3) vec4(comparison_passes(sampleTexture2DMS(TEX_NAME(index), coord3.xy, index).x, coord3.z, ZCOMPARE_FUNC(index)))\n"
|
||||
"#define TEX2D_SHADOWPROJ_MS(index, coord4) TEX2D_SHADOW_MS(index, (coord4.xyz / coord4.w))\n"
|
||||
"#define TEX2D_Z24X8_RGBA8_MS(index, coord2) process_texel(convert_z24x8_to_rgba8(ZS_READ_MS(index, coord2), texture_parameters[index].remap, TEX_FLAGS(index)), TEX_FLAGS(index))\n\n";
|
||||
|
||||
auto insert_msaa_sample_code = [&OS](const std::string_view& sampler_type)
|
||||
{
|
||||
OS <<
|
||||
"vec4 sampleTexture2DMS(in " << sampler_type << " tex, const in vec2 coords, const in int index)\n"
|
||||
"{\n"
|
||||
" const uint flags = TEX_FLAGS(index);\n"
|
||||
" const ivec2 sample_count = ivec2(2, textureSamples(tex) / 2);\n"
|
||||
" const ivec2 icoords = ivec2(COORD_SCALE2(index, coords) * textureSize(tex) * sample_count);\n"
|
||||
"\n"
|
||||
" const ivec2 resolve_coords = icoords * ivec2(bvec2(texture_parameters[index].scale_bias.xy));\n"
|
||||
" const ivec2 aa_coords = resolve_coords / sample_count;\n"
|
||||
" const ivec2 sample_loc = ivec2(resolve_coords % sample_count);\n"
|
||||
" const int sample_index = sample_loc.x + (sample_loc.y * sample_count.y);\n"
|
||||
" return texelFetch(tex, aa_coords, sample_index);\n"
|
||||
"}\n\n";
|
||||
};
|
||||
|
||||
insert_msaa_sample_code("sampler2DMS");
|
||||
if (props.require_depth_conversion)
|
||||
{
|
||||
insert_msaa_sample_code("usampler2DMS");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (props.require_wpos)
|
||||
|
|
@ -984,6 +1021,22 @@ namespace glsl
|
|||
return "TEX3D_Z24X8_RGBA8($_i, $0.xyz)";
|
||||
case FUNCTION::TEXTURE_SAMPLE3D_DEPTH_RGBA_PROJ:
|
||||
return "TEX3D_Z24X8_RGBA8($_i, ($0.xyz / $0.w))";
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS:
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_BIAS:
|
||||
return "TEX2D_MS($_i, $0.xy)";
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_PROJ:
|
||||
return "TEX2D_MS($_i, $0.xy / $0.w)";
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_LOD:
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_GRAD:
|
||||
return "TEX2D_MS($_i, $0.xy)";
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_SHADOW:
|
||||
return "TEX2D_SHADOW_MS($_i, $0.xyz)";
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_SHADOW_PROJ:
|
||||
return "TEX2D_SHADOWPROJ_MS($_i, $0)";
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_DEPTH_RGBA:
|
||||
return "TEX2D_Z24X8_RGBA8_MS($_i, $0.xy)";
|
||||
case FUNCTION::TEXTURE_SAMPLE2DMS_DEPTH_RGBA_PROJ:
|
||||
return "TEX2D_Z24X8_RGBA8_MS($_i, ($0.xy / $0.w))";
|
||||
case FUNCTION::DFDX:
|
||||
return "dFdx($0)";
|
||||
case FUNCTION::DFDY:
|
||||
|
|
@ -995,6 +1048,8 @@ namespace glsl
|
|||
case FUNCTION::VERTEX_TEXTURE_FETCH3D:
|
||||
case FUNCTION::VERTEX_TEXTURE_FETCHCUBE:
|
||||
return "textureLod($t, $0.xyz, 0)";
|
||||
case FUNCTION::VERTEX_TEXTURE_FETCH2DMS:
|
||||
return "texelFetch($t, ivec2($0.xy * textureSize($t)), 0)";
|
||||
}
|
||||
|
||||
rsx_log.error("Unexpected function request: %d", static_cast<int>(f));
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ namespace rsx
|
|||
EXPAND_G,
|
||||
EXPAND_B,
|
||||
DEPTH_FLOAT,
|
||||
DEPTH_COMPARE_OP,
|
||||
DEPTH_COMPARE_1,
|
||||
DEPTH_COMPARE_2,
|
||||
FILTERED,
|
||||
UNNORMALIZED_COORDS,
|
||||
|
||||
GAMMA_CTRL_MASK = (1 << GAMMA_R) | (1 << GAMMA_G) | (1 << GAMMA_B) | (1 << GAMMA_A),
|
||||
EXPAND_MASK = (1 << EXPAND_R) | (1 << EXPAND_G) | (1 << EXPAND_B) | (1 << EXPAND_A),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace glsl
|
|||
bool require_depth_conversion : 1;
|
||||
bool require_texture_ops : 1;
|
||||
bool require_shadow_ops : 1;
|
||||
bool require_msaa_ops : 1;
|
||||
bool require_texture_expand : 1;
|
||||
bool require_srgb_to_linear : 1;
|
||||
bool require_linear_to_srgb : 1;
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ usz vertex_program_storage_hash::operator()(const RSXVertexProgram &program) con
|
|||
usz hash = vertex_program_utils::get_vertex_program_ucode_hash(program);
|
||||
hash ^= program.output_mask;
|
||||
hash ^= program.texture_state.texture_dimensions;
|
||||
hash ^= program.texture_state.multisampled_textures;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -507,6 +508,7 @@ usz fragment_program_storage_hash::operator()(const RSXFragmentProgram& program)
|
|||
hash ^= program.texture_state.texture_dimensions;
|
||||
hash ^= program.texture_state.shadow_textures;
|
||||
hash ^= program.texture_state.redirected_textures;
|
||||
hash ^= program.texture_state.multisampled_textures;
|
||||
hash ^= program.texcoord_control_mask;
|
||||
|
||||
return hash;
|
||||
|
|
|
|||
|
|
@ -308,6 +308,8 @@ struct RSXFragmentProgram
|
|||
|
||||
bool valid = false;
|
||||
|
||||
RSXFragmentProgram() = default;
|
||||
|
||||
rsx::texture_dimension_extended get_texture_dimension(u8 id) const
|
||||
{
|
||||
return rsx::texture_dimension_extended{static_cast<u8>((texture_state.texture_dimensions >> (id * 2)) & 0x3)};
|
||||
|
|
@ -324,10 +326,6 @@ struct RSXFragmentProgram
|
|||
return !!(texcoord_control_mask & (1u << index));
|
||||
}
|
||||
|
||||
RSXFragmentProgram()
|
||||
{
|
||||
}
|
||||
|
||||
static RSXFragmentProgram clone(const RSXFragmentProgram& prog)
|
||||
{
|
||||
auto result = prog;
|
||||
|
|
|
|||
|
|
@ -64,10 +64,21 @@ enum class FUNCTION
|
|||
TEXTURE_SAMPLE3D_DEPTH_RGBA,
|
||||
TEXTURE_SAMPLE3D_DEPTH_RGBA_PROJ,
|
||||
|
||||
TEXTURE_SAMPLE2DMS,
|
||||
TEXTURE_SAMPLE2DMS_BIAS,
|
||||
TEXTURE_SAMPLE2DMS_PROJ,
|
||||
TEXTURE_SAMPLE2DMS_LOD,
|
||||
TEXTURE_SAMPLE2DMS_GRAD,
|
||||
TEXTURE_SAMPLE2DMS_SHADOW,
|
||||
TEXTURE_SAMPLE2DMS_SHADOW_PROJ,
|
||||
TEXTURE_SAMPLE2DMS_DEPTH_RGBA,
|
||||
TEXTURE_SAMPLE2DMS_DEPTH_RGBA_PROJ,
|
||||
|
||||
VERTEX_TEXTURE_FETCH1D,
|
||||
VERTEX_TEXTURE_FETCH2D,
|
||||
VERTEX_TEXTURE_FETCH3D,
|
||||
VERTEX_TEXTURE_FETCHCUBE,
|
||||
VERTEX_TEXTURE_FETCH2DMS,
|
||||
|
||||
// Meta
|
||||
TEXTURE_SAMPLE_MAX_BASE_ENUM = TEXTURE_SAMPLE_DEPTH_RGBA_PROJ_BASE, // Update if more base enums are added
|
||||
|
|
|
|||
|
|
@ -593,13 +593,15 @@ std::string VertexProgramDecompiler::Decompile()
|
|||
case RSX_VEC_OPCODE_TXL:
|
||||
{
|
||||
GetTex();
|
||||
const bool is_multisampled = m_prog.texture_state.multisampled_textures & (1 << d2.tex_num);
|
||||
|
||||
switch (m_prog.get_texture_dimension(d2.tex_num))
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
SetDSTVec(getFunction(FUNCTION::VERTEX_TEXTURE_FETCH1D));
|
||||
SetDSTVec(is_multisampled ? getFunction(FUNCTION::VERTEX_TEXTURE_FETCH2DMS) : getFunction(FUNCTION::VERTEX_TEXTURE_FETCH1D));
|
||||
break;
|
||||
case rsx::texture_dimension_extended::texture_dimension_2d:
|
||||
SetDSTVec(getFunction(FUNCTION::VERTEX_TEXTURE_FETCH2D));
|
||||
SetDSTVec(getFunction(is_multisampled ? FUNCTION::VERTEX_TEXTURE_FETCH2DMS : FUNCTION::VERTEX_TEXTURE_FETCH2D));
|
||||
break;
|
||||
case rsx::texture_dimension_extended::texture_dimension_3d:
|
||||
SetDSTVec(getFunction(FUNCTION::VERTEX_TEXTURE_FETCH3D));
|
||||
|
|
|
|||
|
|
@ -52,18 +52,20 @@ namespace rsx
|
|||
masked_transfer(slots_, src, mask);
|
||||
}
|
||||
|
||||
void fragment_program_texture_state::clear(u32 index)
|
||||
{
|
||||
const u16 clear_mask = ~(static_cast<u16>(1 << index));
|
||||
redirected_textures &= clear_mask;
|
||||
shadow_textures &= clear_mask;
|
||||
}
|
||||
|
||||
void fragment_program_texture_state::import(const fragment_program_texture_state& other, u16 mask)
|
||||
{
|
||||
redirected_textures = other.redirected_textures & mask;
|
||||
shadow_textures = other.shadow_textures & mask;
|
||||
texture_dimensions = other.texture_dimensions & duplicate_and_extend(mask);
|
||||
void fragment_program_texture_state::clear(u32 index)
|
||||
{
|
||||
const u16 clear_mask = ~(static_cast<u16>(1 << index));
|
||||
redirected_textures &= clear_mask;
|
||||
shadow_textures &= clear_mask;
|
||||
multisampled_textures &= clear_mask;
|
||||
}
|
||||
|
||||
void fragment_program_texture_state::import(const fragment_program_texture_state& other, u16 mask)
|
||||
{
|
||||
redirected_textures = other.redirected_textures & mask;
|
||||
shadow_textures = other.shadow_textures & mask;
|
||||
multisampled_textures = other.multisampled_textures & mask;
|
||||
texture_dimensions = other.texture_dimensions & duplicate_and_extend(mask);
|
||||
}
|
||||
|
||||
void fragment_program_texture_state::set_dimension(texture_dimension_extended type, u32 index)
|
||||
|
|
@ -75,19 +77,22 @@ namespace rsx
|
|||
}
|
||||
|
||||
bool fragment_program_texture_state::operator == (const fragment_program_texture_state& other) const
|
||||
{
|
||||
return texture_dimensions == other.texture_dimensions &&
|
||||
redirected_textures == other.redirected_textures &&
|
||||
shadow_textures == other.shadow_textures;
|
||||
}
|
||||
|
||||
void vertex_program_texture_state::clear(u32 /*index*/)
|
||||
{
|
||||
// Nothing to do yet
|
||||
return texture_dimensions == other.texture_dimensions &&
|
||||
redirected_textures == other.redirected_textures &&
|
||||
shadow_textures == other.shadow_textures &&
|
||||
multisampled_textures == other.multisampled_textures;
|
||||
}
|
||||
|
||||
void vertex_program_texture_state::clear(u32 index)
|
||||
{
|
||||
const u16 clear_mask = ~(static_cast<u16>(1 << index));
|
||||
multisampled_textures &= clear_mask;
|
||||
}
|
||||
|
||||
void vertex_program_texture_state::import(const vertex_program_texture_state& other, u16 mask)
|
||||
{
|
||||
multisampled_textures = other.multisampled_textures & mask;
|
||||
texture_dimensions = other.texture_dimensions & duplicate_and_extend(mask);
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +106,7 @@ namespace rsx
|
|||
|
||||
bool vertex_program_texture_state::operator == (const vertex_program_texture_state& other) const
|
||||
{
|
||||
return texture_dimensions == other.texture_dimensions;
|
||||
return texture_dimensions == other.texture_dimensions &&
|
||||
multisampled_textures == other.multisampled_textures;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,14 +33,15 @@ namespace rsx
|
|||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct fragment_program_texture_state
|
||||
{
|
||||
u32 texture_dimensions = 0;
|
||||
u16 redirected_textures = 0;
|
||||
u16 shadow_textures = 0;
|
||||
|
||||
void clear(u32 index);
|
||||
void import(const fragment_program_texture_state& other, u16 mask);
|
||||
struct fragment_program_texture_state
|
||||
{
|
||||
u32 texture_dimensions = 0;
|
||||
u16 redirected_textures = 0;
|
||||
u16 shadow_textures = 0;
|
||||
u16 multisampled_textures = 0;
|
||||
|
||||
void clear(u32 index);
|
||||
void import(const fragment_program_texture_state& other, u16 mask);
|
||||
void set_dimension(texture_dimension_extended type, u32 index);
|
||||
bool operator == (const fragment_program_texture_state& other) const;
|
||||
};
|
||||
|
|
@ -48,6 +49,7 @@ namespace rsx
|
|||
struct vertex_program_texture_state
|
||||
{
|
||||
u32 texture_dimensions = 0;
|
||||
u16 multisampled_textures = 0;
|
||||
|
||||
void clear(u32 index);
|
||||
void import(const vertex_program_texture_state& other, u16 mask);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue