mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-12 02:09:17 +00:00
rsx: Support variable blend target masks with programmable blending
This commit is contained in:
@@ -690,6 +690,12 @@ namespace rsx
|
||||
rop_control.set_output_remap(remap_index);
|
||||
}
|
||||
|
||||
if (fragment_program.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING)
|
||||
{
|
||||
const auto blend_enable_mask = REGS(m_ctx)->blend_enabled_mask() & REGS(m_ctx)->surface_color_target_mask();
|
||||
rop_control.set_blend_target_mask(blend_enable_mask);
|
||||
}
|
||||
|
||||
// Generate wpos coefficients
|
||||
// wpos equation is now as follows (ignoring pixel center offset):
|
||||
// wpos.y = (frag_coord / resolution_scale) * ((window_origin!=top)?-1.: 1.) + ((window_origin!=top)? window_height : 0)
|
||||
|
||||
@@ -43,6 +43,8 @@ namespace rsx
|
||||
zeta_address_is_cyclic = (1 << 26), // The currently bound Z buffer is active for R/W in a cyclic manner
|
||||
zeta_address_cyclic_barrier = (1 << 27), // A memory barrier is required to "end" the Z buffer cyclic state
|
||||
|
||||
blend_config_dirty = (1 << 28), // Blending configuration has been updated. Only matters when programmable blending is in use.
|
||||
|
||||
// TODO - Should signal that we simply need to do a FP compare before the next draw call and invalidate the ucode if the content has changed.
|
||||
// Marking as dirty to invalidate hot cache also works, it's not like there's tons of barriers per frame anyway.
|
||||
fragment_program_needs_rehash = fragment_program_ucode_dirty,
|
||||
|
||||
@@ -210,6 +210,8 @@ namespace glsl
|
||||
{ "FRAG_DEPTH_FLOAT_BIT ", rsx::ROP_control_bits::FRAG_DEPTH_FLOAT_BIT },
|
||||
{ "MRT_CHANNEL_REMAP_OFFSET ", rsx::ROP_control_bits::MRT_CHANNEL_REMAP_OFFSET },
|
||||
{ "MRT_CHANNEL_REMAP_LENGTH ", rsx::ROP_control_bits::MRT_CHANNEL_REMAP_NUM_BITS },
|
||||
{ "MRT_BLEND_TARGETS_OFFSET ", rsx::ROP_control_bits::MRT_BLEND_TARGETS_OFFSET },
|
||||
{ "MRT_BLEND_TARGETS_LENGTH ", rsx::ROP_control_bits::MRT_BLEND_TARGETS_NUM_BITS },
|
||||
{ "ROP_CMD_MASK ", rsx::ROP_control_bits::ROP_CMD_MASK }
|
||||
});
|
||||
|
||||
|
||||
@@ -28,11 +28,13 @@ namespace rsx
|
||||
ALPHA_FUNC_OFFSET = 12,
|
||||
MSAA_SAMPLE_CTRL_OFFSET = 15,
|
||||
MRT_CHANNEL_REMAP_OFFSET = 17,
|
||||
MRT_BLEND_TARGETS_OFFSET = 20,
|
||||
|
||||
// Data lengths
|
||||
ALPHA_FUNC_NUM_BITS = 3,
|
||||
MSAA_SAMPLE_CTRL_NUM_BITS = 2,
|
||||
MRT_CHANNEL_REMAP_NUM_BITS = 3,
|
||||
MRT_BLEND_TARGETS_NUM_BITS = 4,
|
||||
|
||||
// Meta
|
||||
ROP_CMD_MASK = 0xF // Commands are encoded in the lower 4 bits
|
||||
@@ -54,6 +56,7 @@ namespace rsx
|
||||
void set_msaa_control(uint ctrl) { value |= (ctrl << ROP_control_bits::MSAA_SAMPLE_CTRL_OFFSET); }
|
||||
|
||||
void set_output_remap(uint remap) { value |= (remap << ROP_control_bits::MRT_CHANNEL_REMAP_OFFSET); }
|
||||
void set_blend_target_mask(uint mask) { value |= ((mask & 0xF) << ROP_control_bits::MRT_BLEND_TARGETS_OFFSET); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -40,21 +40,13 @@ R"(
|
||||
// ================= Post-output color stages =================
|
||||
#if _MRT_BUFFERS_COUNT >= 1
|
||||
|
||||
#ifdef _ENABLE_PROGRAMMABLE_BLENDING
|
||||
// Stash the raw source data
|
||||
MRT0_DO(vec4 blend_s0 = col0;)
|
||||
MRT1_DO(vec4 blend_s1 = col1;)
|
||||
MRT2_DO(vec4 blend_s2 = col2;)
|
||||
MRT3_DO(vec4 blend_s3 = col3;)
|
||||
#endif
|
||||
|
||||
// NOTE: Blending happens before output remapping as per hardware tests.
|
||||
// Sources = raw shader output, Dest = Remapped output from previous draw
|
||||
#ifdef _ENABLE_PROGRAMMABLE_BLENDING
|
||||
MRT0_DO(col0 = _mrt_color_t(do_blend(blend_s0, mrt_color0));)
|
||||
MRT1_DO(col1 = _mrt_color_t(do_blend(blend_s1, mrt_color1));)
|
||||
MRT2_DO(col2 = _mrt_color_t(do_blend(blend_s2, mrt_color2));)
|
||||
MRT3_DO(col3 = _mrt_color_t(do_blend(blend_s3, mrt_color3));)
|
||||
MRT0_BLEND_DO(col0 = _mrt_color_t(do_blend(col0, mrt_color0));)
|
||||
MRT1_BLEND_DO(col1 = _mrt_color_t(do_blend(col1, mrt_color1));)
|
||||
MRT2_BLEND_DO(col2 = _mrt_color_t(do_blend(col2, mrt_color2));)
|
||||
MRT3_BLEND_DO(col3 = _mrt_color_t(do_blend(col3, mrt_color3));)
|
||||
#endif
|
||||
|
||||
#ifdef _ENABLE_ROP_CHANNEL_REMAPPING
|
||||
|
||||
@@ -22,7 +22,7 @@ R"(
|
||||
#if _MRT_BUFFERS_COUNT >= 1
|
||||
#define MRT0_DO(expr) expr
|
||||
#else
|
||||
#define MRT0_DO(expr) expr
|
||||
#define MRT0_DO(expr)
|
||||
#endif
|
||||
#if _MRT_BUFFERS_COUNT >= 2
|
||||
#define MRT1_DO(expr) expr
|
||||
@@ -47,23 +47,29 @@ const uint ROP_remap = get_ROP_channel_remap();
|
||||
#endif
|
||||
|
||||
#ifdef _ENABLE_PROGRAMMABLE_BLENDING
|
||||
#define IS_MRT_BLEND_ENABLED(n) _test_bit(rop_control, (n) + MRT_BLEND_TARGETS_OFFSET)
|
||||
#define FRAG_LOAD(n) mrt_color##n = subpassLoad(frag_src_##n)
|
||||
|
||||
#define MRT0_BLEND_DO(expr) MRT0_DO(if (IS_MRT_BLEND_ENABLED(0)) expr)
|
||||
#define MRT1_BLEND_DO(expr) MRT1_DO(if (IS_MRT_BLEND_ENABLED(1)) expr)
|
||||
#define MRT2_BLEND_DO(expr) MRT2_DO(if (IS_MRT_BLEND_ENABLED(2)) expr)
|
||||
#define MRT3_BLEND_DO(expr) MRT3_DO(if (IS_MRT_BLEND_ENABLED(3)) expr)
|
||||
|
||||
MRT0_DO(vec4 mrt_color0;)
|
||||
MRT1_DO(vec4 mrt_color1;)
|
||||
MRT2_DO(vec4 mrt_color2;)
|
||||
MRT3_DO(vec4 mrt_color3;)
|
||||
|
||||
MRT0_DO(FRAG_LOAD(0);)
|
||||
MRT1_DO(FRAG_LOAD(1);)
|
||||
MRT2_DO(FRAG_LOAD(2);)
|
||||
MRT3_DO(FRAG_LOAD(3);)
|
||||
MRT0_BLEND_DO(FRAG_LOAD(0);)
|
||||
MRT1_BLEND_DO(FRAG_LOAD(1);)
|
||||
MRT2_BLEND_DO(FRAG_LOAD(2);)
|
||||
MRT3_BLEND_DO(FRAG_LOAD(3);)
|
||||
|
||||
#ifdef _ENABLE_ROP_CHANNEL_REMAPPING
|
||||
MRT0_DO(mrt_color0 = _mrt_color_t(remap_ROP_input(mrt_color0, ROP_remap));)
|
||||
MRT1_DO(mrt_color1 = _mrt_color_t(remap_ROP_input(mrt_color1, ROP_remap));)
|
||||
MRT2_DO(mrt_color2 = _mrt_color_t(remap_ROP_input(mrt_color2, ROP_remap));)
|
||||
MRT3_DO(mrt_color3 = _mrt_color_t(remap_ROP_input(mrt_color3, ROP_remap));)
|
||||
MRT0_BLEND_DO(mrt_color0 = _mrt_color_t(remap_ROP_input(mrt_color0, ROP_remap));)
|
||||
MRT1_BLEND_DO(mrt_color1 = _mrt_color_t(remap_ROP_input(mrt_color1, ROP_remap));)
|
||||
MRT2_BLEND_DO(mrt_color2 = _mrt_color_t(remap_ROP_input(mrt_color2, ROP_remap));)
|
||||
MRT3_BLEND_DO(mrt_color3 = _mrt_color_t(remap_ROP_input(mrt_color3, ROP_remap));)
|
||||
#endif // _ENABLE_ROP_CHANNEL_REMAPPING
|
||||
|
||||
#undef FRAG_LOAD
|
||||
|
||||
@@ -299,6 +299,9 @@ namespace rsx
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_blend_config_dirty = RSX(ctx)->m_graphics_state.test(rsx::blend_config_dirty);
|
||||
RSX(ctx)->m_graphics_state.clear(rsx::blend_config_dirty);
|
||||
|
||||
// FIXME: Unimplemented
|
||||
if (RSX(ctx)->get_backend_config().supports_hw_msaa &&
|
||||
REGS(ctx)->surface_antialias() != rsx::surface_antialiasing::center_1_sample)
|
||||
@@ -357,6 +360,11 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
if (need_programmable_blending && is_blend_config_dirty)
|
||||
{
|
||||
RSX(ctx)->m_graphics_state.set(rsx::fragment_state_dirty);
|
||||
}
|
||||
|
||||
if (need_programmable_blending == programmable_blend_active)
|
||||
{
|
||||
return false;
|
||||
@@ -2189,7 +2197,12 @@ namespace rsx
|
||||
if (m_graphics_state.test(rsx::pipeline_config_dirty) &&
|
||||
backend_config.supports_programmable_blending)
|
||||
{
|
||||
evaluate_programmable_blending_state(m_ctx, current_fragment_program);
|
||||
if (evaluate_programmable_blending_state(m_ctx, current_fragment_program) &&
|
||||
(current_fragment_program.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING))
|
||||
{
|
||||
// Reload ROP control
|
||||
m_graphics_state.set(rsx::pipeline_state::fragment_state_dirty);
|
||||
}
|
||||
}
|
||||
|
||||
prefetch_vertex_program();
|
||||
@@ -2333,7 +2346,12 @@ namespace rsx
|
||||
|
||||
if (backend_config.supports_programmable_blending)
|
||||
{
|
||||
evaluate_programmable_blending_state(m_ctx, current_fragment_program);
|
||||
if (evaluate_programmable_blending_state(m_ctx, current_fragment_program) &&
|
||||
!!(current_fragment_program.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING))
|
||||
{
|
||||
// Reload ROP control bits. Is this really needed here?
|
||||
m_graphics_state.set(rsx::pipeline_state::fragment_state_dirty);
|
||||
}
|
||||
}
|
||||
|
||||
const bool zeta_was_cyclic = m_graphics_state & rsx::zeta_address_is_cyclic;
|
||||
|
||||
@@ -775,8 +775,8 @@ namespace rsx
|
||||
state_signals[NV4097_SET_ZMIN_MAX_CONTROL] = rsx::pipeline_config_dirty;
|
||||
state_signals[NV4097_SET_LOGIC_OP_ENABLE] = rsx::pipeline_config_dirty;
|
||||
state_signals[NV4097_SET_LOGIC_OP] = rsx::pipeline_config_dirty;
|
||||
state_signals[NV4097_SET_BLEND_ENABLE] = rsx::pipeline_config_dirty;
|
||||
state_signals[NV4097_SET_BLEND_ENABLE_MRT] = rsx::pipeline_config_dirty;
|
||||
state_signals[NV4097_SET_BLEND_ENABLE] = rsx::pipeline_config_dirty | rsx::blend_config_dirty;
|
||||
state_signals[NV4097_SET_BLEND_ENABLE_MRT] = rsx::pipeline_config_dirty | rsx::blend_config_dirty;
|
||||
state_signals[NV4097_SET_STENCIL_FUNC] = rsx::pipeline_config_dirty;
|
||||
state_signals[NV4097_SET_BACK_STENCIL_FUNC] = rsx::pipeline_config_dirty;
|
||||
state_signals[NV4097_SET_RESTART_INDEX_ENABLE] = rsx::pipeline_config_dirty;
|
||||
|
||||
Reference in New Issue
Block a user