mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-05-12 16:19:44 -06:00
rsx: Make emulated Z operations compatible with MSAA
This commit is contained in:
parent
c7ff1e726c
commit
d5018ee3ea
@ -169,7 +169,11 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
|
||||
if (m_prog.ctrl & RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE)
|
||||
{
|
||||
OS << "uniform sampler2D frag_depth;\n";
|
||||
const auto frag_depth_type = (m_prog.ctrl & RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER)
|
||||
? "sampler2DMS"
|
||||
: "sampler2D";
|
||||
|
||||
OS << "uniform " << frag_depth_type << " frag_depth;\n";
|
||||
}
|
||||
|
||||
OS << "\n";
|
||||
@ -244,6 +248,7 @@ void GLFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
|
||||
m_shader_props.require_alpha_kill = !!(m_prog.ctrl & RSX_SHADER_CONTROL_TEXTURE_ALPHA_KILL);
|
||||
m_shader_props.require_color_format_convert = !!(m_prog.ctrl & RSX_SHADER_CONTROL_TEXTURE_FORMAT_CONVERT);
|
||||
m_shader_props.emulate_depth_compare = !!(m_prog.ctrl & RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE);
|
||||
m_shader_props.depth_buffer_multisampled = !!(m_prog.ctrl & RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER);
|
||||
|
||||
glsl::insert_glsl_legacy_function(OS, m_shader_props);
|
||||
}
|
||||
|
||||
@ -116,7 +116,8 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
|
||||
rsx::rtt_config_dirty |
|
||||
rsx::rtt_config_contested |
|
||||
rsx::rtt_config_valid |
|
||||
rsx::rtt_cache_state_dirty);
|
||||
rsx::rtt_cache_state_dirty |
|
||||
rsx::pipeline_config_dirty);
|
||||
|
||||
get_framebuffer_layout(context, m_framebuffer_layout);
|
||||
if (!m_graphics_state.test(rsx::rtt_config_valid))
|
||||
|
||||
@ -272,15 +272,6 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
void set_depth_func(context* ctx, u32 reg, u32 arg)
|
||||
{
|
||||
if (arg != REGS(ctx)->latch)
|
||||
{
|
||||
set_surface_options_dirty_bit(ctx, reg, arg);
|
||||
RSX(ctx)->m_graphics_state |= rsx::pipeline_state::fragment_program_state_dirty;
|
||||
}
|
||||
}
|
||||
|
||||
void set_color_mask(context* ctx, u32 reg, u32 arg)
|
||||
{
|
||||
if (arg == REGS(ctx)->latch)
|
||||
|
||||
@ -89,8 +89,6 @@ namespace rsx
|
||||
|
||||
void set_aa_control(context* ctx, u32 reg, u32 arg);
|
||||
|
||||
void set_depth_func(context* ctx, u32 reg, u32 arg);
|
||||
|
||||
#define RSX(ctx) ctx->rsxthr
|
||||
#define REGS(ctx) (&rsx::method_registers)
|
||||
|
||||
|
||||
@ -247,6 +247,11 @@ namespace glsl
|
||||
{
|
||||
enabled_options.push_back("_ENABLE_DEPTH_COMPARE");
|
||||
}
|
||||
|
||||
if (props.depth_buffer_multisampled)
|
||||
{
|
||||
enabled_options.push_back("_ENABLE_DEPTH_BUFFER_MULTISAMPLED");
|
||||
}
|
||||
}
|
||||
|
||||
// Import common header
|
||||
|
||||
@ -39,7 +39,11 @@ R"(
|
||||
#endif
|
||||
|
||||
#ifdef _ENABLE_DEPTH_COMPARE
|
||||
#ifdef _ENABLE_DEPTH_BUFFER_MULTISAMPLED
|
||||
float dstDepth = texelFetch(frag_depth, ivec2(gl_FragCoord.xy), gl_SampleID).r;
|
||||
#else
|
||||
float dstDepth = texelFetch(frag_depth, ivec2(gl_FragCoord.xy), 0).r;
|
||||
#endif
|
||||
float srcDepth = gl_FragCoord.z;
|
||||
float scale = _test_bit(rop_control, FRAG_DEPTH_24_BIT) ? float(0xffffffu) : float(0xffffu);
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ namespace glsl
|
||||
bool require_fog_read : 1;
|
||||
bool emulate_shadow_compare : 1;
|
||||
bool emulate_depth_compare : 1;
|
||||
bool depth_buffer_multisampled : 1;
|
||||
bool low_precision_tests : 1;
|
||||
bool disable_early_discard : 1;
|
||||
bool supports_native_fp16 : 1;
|
||||
|
||||
@ -1681,15 +1681,6 @@ namespace rsx
|
||||
m_frame_stats.framebuffer_stats.add(layout.width, layout.height, aa_mode);
|
||||
}
|
||||
|
||||
// Flags
|
||||
if (g_cfg.video.emulate_depth_compare &&
|
||||
m_framebuffer_layout.zeta_address &&
|
||||
method_registers.depth_func() == rsx::comparison_function::equal)
|
||||
{
|
||||
current_fragment_program.ctrl |= RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE;
|
||||
current_fragment_program.ctrl &= ~RSX_SHADER_CONTROL_DISABLE_EARLY_Z;
|
||||
}
|
||||
|
||||
// Check if anything has changed
|
||||
bool really_changed = false;
|
||||
|
||||
@ -1975,6 +1966,36 @@ namespace rsx
|
||||
return true;
|
||||
}
|
||||
|
||||
rsx::flags32_t thread::get_fragment_program_export_config()
|
||||
{
|
||||
if (!g_cfg.video.emulate_depth_compare) [[ likely ]]
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_ctx->register_state->current_draw_clause.classify_mode() != primitive_class::polygon)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 expected_ctrl = 0;
|
||||
|
||||
if (m_framebuffer_layout.zeta_address &&
|
||||
m_ctx->register_state->depth_test_enabled() &&
|
||||
m_ctx->register_state->depth_func() == rsx::comparison_function::equal)
|
||||
{
|
||||
expected_ctrl |= RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE;
|
||||
|
||||
if (backend_config.supports_hw_msaa &&
|
||||
m_ctx->register_state->surface_antialias() != rsx::surface_antialiasing::center_1_sample)
|
||||
{
|
||||
expected_ctrl |= RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER;
|
||||
}
|
||||
}
|
||||
|
||||
return expected_ctrl;
|
||||
}
|
||||
|
||||
void thread::prefetch_fragment_program()
|
||||
{
|
||||
if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_ucode_dirty))
|
||||
@ -2069,6 +2090,18 @@ namespace rsx
|
||||
{
|
||||
m_program_cache_hint.invalidate(m_graphics_state.load());
|
||||
|
||||
constexpr u32 fs_export_config_mask = (RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE | RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER);
|
||||
if (u32 export_ctrl = get_fragment_program_export_config();
|
||||
(current_fragment_program.ctrl & fs_export_config_mask) != export_ctrl)
|
||||
{
|
||||
// Update control bits for immediate consumers
|
||||
current_fragment_program.ctrl &= ~fs_export_config_mask;
|
||||
current_fragment_program.ctrl |= export_ctrl;
|
||||
|
||||
// Signal backend to reload pipeline
|
||||
m_graphics_state.set(rsx::pipeline_state::fragment_state_dirty);
|
||||
}
|
||||
|
||||
prefetch_vertex_program();
|
||||
prefetch_fragment_program();
|
||||
}
|
||||
@ -2163,12 +2196,7 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cfg.video.emulate_depth_compare &&
|
||||
m_framebuffer_layout.zeta_address &&
|
||||
method_registers.depth_func() == rsx::comparison_function::equal)
|
||||
{
|
||||
current_fragment_program.ctrl |= RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE;
|
||||
}
|
||||
current_fragment_program.ctrl |= get_fragment_program_export_config();
|
||||
}
|
||||
else if (m_ctx->register_state->point_sprite_enabled() &&
|
||||
m_ctx->register_state->current_draw_clause.primitive == primitive_type::points)
|
||||
|
||||
@ -280,11 +280,13 @@ namespace rsx
|
||||
// Prefetch and analyze the currently active vertex program ucode
|
||||
void prefetch_vertex_program();
|
||||
|
||||
// Update fragment program export configuration. Can invalidate the current program.
|
||||
rsx::flags32_t get_fragment_program_export_config();
|
||||
|
||||
// Gets the current vertex program and associated state. Can invalidate the bound progam.
|
||||
void get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors);
|
||||
|
||||
/**
|
||||
* Gets current fragment program and associated fragment state
|
||||
*/
|
||||
// Gets current fragment program and associated fragment state. Can invalidate the bound program.
|
||||
void get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors);
|
||||
|
||||
public:
|
||||
|
||||
@ -607,6 +607,16 @@ void VKGSRender::load_texture_env()
|
||||
|
||||
m_samplers_dirty.store(false);
|
||||
|
||||
if (current_fragment_program.ctrl & RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE)
|
||||
{
|
||||
// Transition our FBO to a loop-friendly format.
|
||||
// We can also convert it into an input attachment, but for now this is easier.
|
||||
auto ds = ensure(m_rtts.m_bound_depth_stencil.second, "Invalid FS export configuration.");
|
||||
ds->texture_barrier(*m_current_command_buffer);
|
||||
|
||||
check_for_cyclic_refs = true;
|
||||
}
|
||||
|
||||
if (check_for_cyclic_refs)
|
||||
{
|
||||
// Regenerate renderpass key
|
||||
@ -771,8 +781,6 @@ bool VKGSRender::bind_texture_env()
|
||||
if (current_fragment_program.ctrl & RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE)
|
||||
{
|
||||
auto ds = ensure(m_rtts.m_bound_depth_stencil.second);
|
||||
vk::insert_texture_barrier(*m_current_command_buffer, ds, VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT, true);
|
||||
|
||||
auto view = ds->get_view(rsx::default_remap_vector, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
m_program->bind_uniform({ *view, vk::null_sampler() }, vk::glsl::binding_set_index_fragment, m_fs_binding_table->frag_depth_input_location);
|
||||
}
|
||||
|
||||
@ -247,7 +247,11 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
|
||||
if (m_prog.ctrl & RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE)
|
||||
{
|
||||
OS << "layout(set=" << vk::glsl::binding_set_index_fragment << ", binding=" << vk_prog->binding_table.frag_depth_input_location << ") uniform sampler2D frag_depth;\n";
|
||||
const auto frag_depth_type = (m_prog.ctrl & RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER)
|
||||
? "sampler2DMS"
|
||||
: "sampler2D";
|
||||
|
||||
OS << "layout(set=" << vk::glsl::binding_set_index_fragment << ", binding=" << vk_prog->binding_table.frag_depth_input_location << ") uniform " << frag_depth_type << " frag_depth;\n";
|
||||
|
||||
auto in = vk::glsl::program_input::make(
|
||||
glsl::glsl_fragment_program,
|
||||
@ -361,6 +365,7 @@ void VKFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
|
||||
m_shader_props.require_alpha_kill = !!(m_prog.ctrl & RSX_SHADER_CONTROL_TEXTURE_ALPHA_KILL);
|
||||
m_shader_props.require_color_format_convert = !!(m_prog.ctrl & RSX_SHADER_CONTROL_TEXTURE_FORMAT_CONVERT);
|
||||
m_shader_props.emulate_depth_compare = !!(m_prog.ctrl & RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE);
|
||||
m_shader_props.depth_buffer_multisampled = !!(m_prog.ctrl & RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER);
|
||||
|
||||
// Declare global constants
|
||||
if (m_shader_props.require_fog_read)
|
||||
|
||||
@ -443,33 +443,35 @@ namespace gcm
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT = 0xe, ///< shader program exports the depth of the shaded fragment
|
||||
CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS = 0x40, ///< shader program exports 32 bits registers values (instead of 16 bits ones)
|
||||
CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT = 0x0000000e, ///< shader program exports the depth of the shaded fragment
|
||||
CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS = 0x00000040, ///< shader program exports 32 bits registers values (instead of 16 bits ones)
|
||||
|
||||
// Other known flags
|
||||
RSX_SHADER_CONTROL_USED_REGS_MASK = 0xf,
|
||||
RSX_SHADER_CONTROL_USED_TEMP_REGS_MASK = 0xff << 24,
|
||||
RSX_SHADER_CONTROL_USES_KIL = 0x80, // program uses KIL op
|
||||
RSX_SHADER_CONTROL_UNKNOWN0 = 0x400, // seemingly always set
|
||||
RSX_SHADER_CONTROL_UNKNOWN1 = 0x8000, // seemingly set when srgb packer is used??
|
||||
RSX_SHADER_CONTROL_USED_REGS_MASK = 0x0000000f,
|
||||
RSX_SHADER_CONTROL_USED_TEMP_REGS_MASK = 0xff000000,
|
||||
|
||||
RSX_SHADER_CONTROL_USES_KIL = 0x00000080, // program uses KIL op
|
||||
RSX_SHADER_CONTROL_UNKNOWN0 = 0x00000400, // seemingly always set
|
||||
RSX_SHADER_CONTROL_UNKNOWN1 = 0x00008000, // seemingly set when srgb packer is used??
|
||||
|
||||
// Custom
|
||||
RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION = 0x00010000, // Rasterizing triangles and not lines or points
|
||||
RSX_SHADER_CONTROL_INSTANCED_CONSTANTS = 0x00020000, // Support instance ID offsets when loading constants
|
||||
RSX_SHADER_CONTROL_INTERPRETER_MODEL = 0x00040000, // Compile internals expecting interpreter
|
||||
RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION = 0x00010000, // Rasterizing triangles and not lines or points
|
||||
RSX_SHADER_CONTROL_INSTANCED_CONSTANTS = 0x00020000, // Support instance ID offsets when loading constants
|
||||
RSX_SHADER_CONTROL_INTERPRETER_MODEL = 0x00040000, // Compile internals expecting interpreter
|
||||
|
||||
RSX_SHADER_CONTROL_8BIT_FRAMEBUFFER = 0x00080000, // Quantize outputs to 8-bit FBO
|
||||
RSX_SHADER_CONTROL_SRGB_FRAMEBUFFER = 0x00100000, // Outputs are SRGB. We could reuse UNKNOWN1 but we just keep the namespaces separate.
|
||||
RSX_SHADER_CONTROL_8BIT_FRAMEBUFFER = 0x00080000, // Quantize outputs to 8-bit FBO
|
||||
RSX_SHADER_CONTROL_SRGB_FRAMEBUFFER = 0x00100000, // Outputs are SRGB. We could reuse UNKNOWN1 but we just keep the namespaces separate.
|
||||
|
||||
RSX_SHADER_CONTROL_TEXTURE_ALPHA_KILL = 0x00200000, // Uses alpha kill on texture input
|
||||
RSX_SHADER_CONTROL_ALPHA_TEST = 0x00400000, // Uses alpha test on the outputs
|
||||
RSX_SHADER_CONTROL_POLYGON_STIPPLE = 0x00800000, // Uses polygon stipple for dithered rendering
|
||||
RSX_SHADER_CONTROL_ALPHA_TO_COVERAGE = 0x01000000, // Alpha to coverage
|
||||
RSX_SHADER_CONTROL_TEXTURE_ALPHA_KILL = 0x00200000, // Uses alpha kill on texture input
|
||||
RSX_SHADER_CONTROL_ALPHA_TEST = 0x00400000, // Uses alpha test on the outputs
|
||||
RSX_SHADER_CONTROL_POLYGON_STIPPLE = 0x00800000, // Uses polygon stipple for dithered rendering
|
||||
RSX_SHADER_CONTROL_ALPHA_TO_COVERAGE = 0x01000000, // Alpha to coverage
|
||||
|
||||
RSX_SHADER_CONTROL_DISABLE_EARLY_Z = 0x02000000, // Do not allow early-Z optimizations on this shader
|
||||
RSX_SHADER_CONTROL_DISABLE_EARLY_Z = 0x02000000, // Do not allow early-Z optimizations on this shader
|
||||
|
||||
RSX_SHADER_CONTROL_TEXTURE_FORMAT_CONVERT = 0x04000000, // Allow format conversions (BX2, SNORM, SRGB, RENORM)
|
||||
RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE = 0x08000000, // Emulate depth comparisons
|
||||
RSX_SHADER_CONTROL_TEXTURE_FORMAT_CONVERT = 0x04000000, // Allow format conversions (BX2, SNORM, SRGB, RENORM)
|
||||
RSX_SHADER_CONTROL_EMULATE_DEPTH_COMPARE = 0x08000000, // Emulate depth comparisons
|
||||
RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER = 0x10000000, // Z buffer is multisampled. Only affects depth comparison behavior at this time.
|
||||
|
||||
// Meta
|
||||
RSX_SHADER_CONTROL_META_USES_DISCARD = (RSX_SHADER_CONTROL_USES_KIL | RSX_SHADER_CONTROL_TEXTURE_ALPHA_KILL | RSX_SHADER_CONTROL_ALPHA_TEST | RSX_SHADER_CONTROL_POLYGON_STIPPLE | RSX_SHADER_CONTROL_ALPHA_TO_COVERAGE)
|
||||
|
||||
@ -1686,7 +1686,7 @@ namespace rsx
|
||||
bind(NV4097_SET_ZPASS_PIXEL_COUNT_ENABLE, nv4097::set_zcull_pixel_count_enable);
|
||||
bind(NV4097_CLEAR_ZCULL_SURFACE, nv4097::clear_zcull);
|
||||
bind(NV4097_SET_DEPTH_TEST_ENABLE, nv4097::set_surface_options_dirty_bit);
|
||||
bind(NV4097_SET_DEPTH_FUNC, nv4097::set_depth_func);
|
||||
bind(NV4097_SET_DEPTH_FUNC, nv4097::set_surface_options_dirty_bit);
|
||||
bind(NV4097_SET_DEPTH_MASK, nv4097::set_surface_options_dirty_bit);
|
||||
bind(NV4097_SET_COLOR_MASK, nv4097::set_color_mask);
|
||||
bind(NV4097_SET_COLOR_MASK_MRT, nv4097::set_surface_options_dirty_bit);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user