rsx/vk: Rework MSAA implementation

This commit is contained in:
kd-11 2022-03-13 11:32:04 +03:00 committed by kd-11
parent 9c5ed01130
commit bc7ed8eaab
30 changed files with 285 additions and 123 deletions

View file

@ -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)
{

View file

@ -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;

View file

@ -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));

View file

@ -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),

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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));

View file

@ -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;
}
}

View file

@ -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);