mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-11 01:08:39 +12:00
rsx: Fix graphics state foot-gun
This commit is contained in:
parent
52b67b46fc
commit
6adcabda29
11 changed files with 150 additions and 67 deletions
|
@ -35,6 +35,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename bitmask_type = u32>
|
template <typename T, typename bitmask_type = u32>
|
||||||
|
requires std::is_integral_v<bitmask_type>&& std::is_enum_v<T>
|
||||||
class atomic_bitmask_t
|
class atomic_bitmask_t
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -95,4 +96,70 @@ namespace rsx
|
||||||
return m_data.observe() != 0;
|
return m_data.observe() != 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, typename bitmask_type = u32>
|
||||||
|
requires std::is_integral_v<bitmask_type> && std::is_enum_v<T>
|
||||||
|
class bitmask_t
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bitmask_type m_data = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bitmask_t() = default;
|
||||||
|
|
||||||
|
bool operator & (bitmask_type mask) const
|
||||||
|
{
|
||||||
|
return !!(m_data & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmask_type operator | (bitmask_type mask) const
|
||||||
|
{
|
||||||
|
return m_data | mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator &= (bitmask_type mask)
|
||||||
|
{
|
||||||
|
m_data &= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator |= (bitmask_type mask)
|
||||||
|
{
|
||||||
|
m_data |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test(T mask)
|
||||||
|
{
|
||||||
|
return !!(m_data & static_cast<bitmask_type>(mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(T mask)
|
||||||
|
{
|
||||||
|
m_data |= static_cast<bitmask_type>(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_and_set(T mask)
|
||||||
|
{
|
||||||
|
const auto old = m_data;
|
||||||
|
m_data |= static_cast<bitmask_type>(mask);
|
||||||
|
return !!(old & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
requires std::is_same_v<T, U> || std::is_same_v<bitmask_type, U>
|
||||||
|
void clear(U mask)
|
||||||
|
{
|
||||||
|
const bitmask_type clear_mask = ~(static_cast<bitmask_type>(mask));
|
||||||
|
m_data &= clear_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return !!m_data;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,7 +320,7 @@ void GLGSRender::update_draw_state()
|
||||||
//NV4097_SET_CLIP_ID_TEST_ENABLE
|
//NV4097_SET_CLIP_ID_TEST_ENABLE
|
||||||
|
|
||||||
// For OGL Z range is updated every draw as it is separate from viewport config
|
// For OGL Z range is updated every draw as it is separate from viewport config
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::zclip_config_state_dirty);
|
||||||
|
|
||||||
m_frame_stats.setup_time += m_profiler.duration();
|
m_frame_stats.setup_time += m_profiler.duration();
|
||||||
}
|
}
|
||||||
|
|
|
@ -799,13 +799,13 @@ void GLGSRender::load_program_env()
|
||||||
|
|
||||||
const u32 fragment_constants_size = current_fp_metadata.program_constants_buffer_length;
|
const u32 fragment_constants_size = current_fp_metadata.program_constants_buffer_length;
|
||||||
|
|
||||||
const bool update_transform_constants = !!(m_graphics_state & rsx::pipeline_state::transform_constants_dirty);
|
const bool update_transform_constants = m_graphics_state & rsx::pipeline_state::transform_constants_dirty;
|
||||||
const bool update_fragment_constants = !!(m_graphics_state & rsx::pipeline_state::fragment_constants_dirty) && fragment_constants_size;
|
const bool update_fragment_constants = (m_graphics_state & rsx::pipeline_state::fragment_constants_dirty) && fragment_constants_size;
|
||||||
const bool update_vertex_env = !!(m_graphics_state & rsx::pipeline_state::vertex_state_dirty);
|
const bool update_vertex_env = m_graphics_state & rsx::pipeline_state::vertex_state_dirty;
|
||||||
const bool update_fragment_env = !!(m_graphics_state & rsx::pipeline_state::fragment_state_dirty);
|
const bool update_fragment_env = m_graphics_state & rsx::pipeline_state::fragment_state_dirty;
|
||||||
const bool update_fragment_texture_env = !!(m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty);
|
const bool update_fragment_texture_env = m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty;
|
||||||
const bool update_instruction_buffers = (!!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program));
|
const bool update_instruction_buffers = !!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program);
|
||||||
const bool update_raster_env = (rsx::method_registers.polygon_stipple_enabled() && !!(m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty));
|
const bool update_raster_env = rsx::method_registers.polygon_stipple_enabled() && (m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty);
|
||||||
|
|
||||||
if (manually_flush_ring_buffers)
|
if (manually_flush_ring_buffers)
|
||||||
{
|
{
|
||||||
|
@ -892,7 +892,7 @@ void GLGSRender::load_program_env()
|
||||||
std::memcpy(mapping.first, rsx::method_registers.polygon_stipple_pattern(), 128);
|
std::memcpy(mapping.first, rsx::method_registers.polygon_stipple_pattern(), 128);
|
||||||
m_raster_env_ring_buffer->bind_range(GL_RASTERIZER_STATE_BIND_SLOT, mapping.second, 128);
|
m_raster_env_ring_buffer->bind_range(GL_RASTERIZER_STATE_BIND_SLOT, mapping.second, 128);
|
||||||
|
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::polygon_stipple_pattern_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::polygon_stipple_pattern_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_instruction_buffers)
|
if (update_instruction_buffers)
|
||||||
|
@ -954,8 +954,12 @@ void GLGSRender::load_program_env()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 handled_flags = (rsx::pipeline_state::fragment_state_dirty | rsx::pipeline_state::vertex_state_dirty | rsx::pipeline_state::transform_constants_dirty | rsx::pipeline_state::fragment_constants_dirty | rsx::pipeline_state::fragment_texture_state_dirty);
|
m_graphics_state.clear(
|
||||||
m_graphics_state &= ~handled_flags;
|
rsx::pipeline_state::fragment_state_dirty |
|
||||||
|
rsx::pipeline_state::vertex_state_dirty |
|
||||||
|
rsx::pipeline_state::transform_constants_dirty |
|
||||||
|
rsx::pipeline_state::fragment_constants_dirty |
|
||||||
|
rsx::pipeline_state::fragment_texture_state_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGSRender::update_vertex_env(const gl::vertex_upload_info& upload_info)
|
void GLGSRender::update_vertex_env(const gl::vertex_upload_info& upload_info)
|
||||||
|
@ -1065,7 +1069,7 @@ void GLGSRender::do_local_task(rsx::FIFO::state state)
|
||||||
//This will re-engage locks and break the texture cache if another thread is waiting in access violation handler!
|
//This will re-engage locks and break the texture cache if another thread is waiting in access violation handler!
|
||||||
//Only call when there are no waiters
|
//Only call when there are no waiters
|
||||||
m_gl_texture_cache.do_update();
|
m_gl_texture_cache.do_update();
|
||||||
m_graphics_state &= ~rsx::pipeline_state::framebuffer_reads_dirty;
|
m_graphics_state.clear(rsx::pipeline_state::framebuffer_reads_dirty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ class GLGSRender : public GSRender, public ::rsx::reports::ZCULL_control
|
||||||
const GLFragmentProgram *m_fragment_prog = nullptr;
|
const GLFragmentProgram *m_fragment_prog = nullptr;
|
||||||
const GLVertexProgram *m_vertex_prog = nullptr;
|
const GLVertexProgram *m_vertex_prog = nullptr;
|
||||||
|
|
||||||
u32 m_interpreter_state = 0;
|
rsx::flags32_t m_interpreter_state = 0;
|
||||||
gl::shader_interpreter m_shader_interpreter;
|
gl::shader_interpreter m_shader_interpreter;
|
||||||
|
|
||||||
gl_render_targets m_rtts;
|
gl_render_targets m_rtts;
|
||||||
|
|
|
@ -409,11 +409,11 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (m_draw_fbo && !m_rtts_dirty)
|
if (m_draw_fbo && !m_graphics_state.test(rsx::rtt_config_dirty))
|
||||||
{
|
{
|
||||||
// Always restore the active framebuffer
|
// Always restore the active framebuffer
|
||||||
m_draw_fbo->bind();
|
m_draw_fbo->bind();
|
||||||
set_viewport();
|
set_viewport();
|
||||||
set_scissor(!!(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped));
|
set_scissor(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ u8 rsx::internals::get_pixel_size(rsx::surface_depth_format format)
|
||||||
void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*skip_reading*/)
|
void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*skip_reading*/)
|
||||||
{
|
{
|
||||||
const bool clipped_scissor = (context == rsx::framebuffer_creation_context::context_draw);
|
const bool clipped_scissor = (context == rsx::framebuffer_creation_context::context_draw);
|
||||||
if (m_current_framebuffer_context == context && !m_rtts_dirty && m_draw_fbo)
|
if (m_current_framebuffer_context == context && !m_graphics_state.test(rsx::rtt_config_dirty) && m_draw_fbo)
|
||||||
{
|
{
|
||||||
// Fast path
|
// Fast path
|
||||||
// Framebuffer usage has not changed, framebuffer exists and config regs have not changed
|
// Framebuffer usage has not changed, framebuffer exists and config regs have not changed
|
||||||
|
@ -111,9 +111,8 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /*
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rtts_dirty = false;
|
m_graphics_state.clear(rsx::rtt_config_dirty | rsx::rtt_config_contested);
|
||||||
framebuffer_status_valid = false;
|
framebuffer_status_valid = false;
|
||||||
m_framebuffer_state_contested = false;
|
|
||||||
|
|
||||||
get_framebuffer_layout(context, m_framebuffer_layout);
|
get_framebuffer_layout(context, m_framebuffer_layout);
|
||||||
if (!framebuffer_status_valid)
|
if (!framebuffer_status_valid)
|
||||||
|
|
|
@ -524,11 +524,10 @@ namespace rsx
|
||||||
return on_access_violation(address, is_writing);
|
return on_access_violation(address, is_writing);
|
||||||
};
|
};
|
||||||
|
|
||||||
m_rtts_dirty = true;
|
|
||||||
m_textures_dirty.fill(true);
|
m_textures_dirty.fill(true);
|
||||||
m_vertex_textures_dirty.fill(true);
|
m_vertex_textures_dirty.fill(true);
|
||||||
|
|
||||||
m_graphics_state = pipeline_state::all_dirty;
|
m_graphics_state |= pipeline_state::all_dirty;
|
||||||
|
|
||||||
g_user_asked_for_frame_capture = false;
|
g_user_asked_for_frame_capture = false;
|
||||||
|
|
||||||
|
@ -685,7 +684,7 @@ namespace rsx
|
||||||
push_buf.clear();
|
push_buf.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_graphics_state &= ~rsx::pipeline_state::push_buffer_arrays_dirty;
|
m_graphics_state.clear(rsx::pipeline_state::push_buffer_arrays_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
element_push_buffer.clear();
|
element_push_buffer.clear();
|
||||||
|
@ -1359,8 +1358,8 @@ namespace rsx
|
||||||
layout.width = rsx::method_registers.surface_clip_width();
|
layout.width = rsx::method_registers.surface_clip_width();
|
||||||
layout.height = rsx::method_registers.surface_clip_height();
|
layout.height = rsx::method_registers.surface_clip_height();
|
||||||
|
|
||||||
|
m_graphics_state.clear(rsx::rtt_config_contested);
|
||||||
framebuffer_status_valid = false;
|
framebuffer_status_valid = false;
|
||||||
m_framebuffer_state_contested = false;
|
|
||||||
m_current_framebuffer_context = context;
|
m_current_framebuffer_context = context;
|
||||||
|
|
||||||
if (layout.width == 0 || layout.height == 0)
|
if (layout.width == 0 || layout.height == 0)
|
||||||
|
@ -1481,7 +1480,10 @@ namespace rsx
|
||||||
}
|
}
|
||||||
|
|
||||||
color_buffer_unused = !color_write_enabled || layout.target == rsx::surface_target::none;
|
color_buffer_unused = !color_write_enabled || layout.target == rsx::surface_target::none;
|
||||||
m_framebuffer_state_contested = color_buffer_unused || depth_buffer_unused;
|
if (color_buffer_unused || depth_buffer_unused)
|
||||||
|
{
|
||||||
|
m_graphics_state.set(rsx::rtt_config_contested);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fmt::throw_exception("Unknown framebuffer context 0x%x", static_cast<u32>(context));
|
fmt::throw_exception("Unknown framebuffer context 0x%x", static_cast<u32>(context));
|
||||||
|
@ -1686,7 +1688,7 @@ namespace rsx
|
||||||
|
|
||||||
void thread::on_framebuffer_options_changed(u32 opt)
|
void thread::on_framebuffer_options_changed(u32 opt)
|
||||||
{
|
{
|
||||||
if (m_rtts_dirty)
|
if (m_graphics_state & rsx::rtt_config_dirty)
|
||||||
{
|
{
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
return;
|
return;
|
||||||
|
@ -1773,9 +1775,9 @@ namespace rsx
|
||||||
{
|
{
|
||||||
evaluate_depth_buffer_state();
|
evaluate_depth_buffer_state();
|
||||||
|
|
||||||
if (m_framebuffer_state_contested)
|
if (m_graphics_state.test(rsx::rtt_config_contested) && evaluate_depth_buffer_contested())
|
||||||
{
|
{
|
||||||
m_rtts_dirty |= evaluate_depth_buffer_contested();
|
m_graphics_state.set(rsx::rtt_config_dirty);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1798,16 +1800,16 @@ namespace rsx
|
||||||
evaluate_stencil_buffer_state();
|
evaluate_stencil_buffer_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_framebuffer_state_contested)
|
if (m_graphics_state.test(rsx::rtt_config_contested) && evaluate_depth_buffer_contested())
|
||||||
{
|
{
|
||||||
m_rtts_dirty |= evaluate_depth_buffer_contested();
|
m_graphics_state.set(rsx::rtt_config_dirty);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NV4097_SET_COLOR_MASK:
|
case NV4097_SET_COLOR_MASK:
|
||||||
case NV4097_SET_COLOR_MASK_MRT:
|
case NV4097_SET_COLOR_MASK_MRT:
|
||||||
{
|
{
|
||||||
if (!m_framebuffer_state_contested) [[likely]]
|
if (!m_graphics_state.test(rsx::rtt_config_contested)) [[likely]]
|
||||||
{
|
{
|
||||||
// Update write masks and continue
|
// Update write masks and continue
|
||||||
evaluate_color_buffer_state();
|
evaluate_color_buffer_state();
|
||||||
|
@ -1824,7 +1826,7 @@ namespace rsx
|
||||||
if (!old_state && new_state)
|
if (!old_state && new_state)
|
||||||
{
|
{
|
||||||
// Color buffers now in use
|
// Color buffers now in use
|
||||||
m_rtts_dirty = true;
|
m_graphics_state.set(rsx::rtt_config_dirty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1836,16 +1838,16 @@ namespace rsx
|
||||||
|
|
||||||
bool thread::get_scissor(areau& region, bool clip_viewport)
|
bool thread::get_scissor(areau& region, bool clip_viewport)
|
||||||
{
|
{
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty))
|
if (!m_graphics_state.test(rsx::pipeline_state::scissor_config_state_dirty))
|
||||||
{
|
{
|
||||||
if (clip_viewport == !!(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped))
|
if (clip_viewport == m_graphics_state.test(rsx::pipeline_state::scissor_setup_clipped))
|
||||||
{
|
{
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::scissor_config_state_dirty | rsx::pipeline_state::scissor_setup_clipped);
|
m_graphics_state.clear(rsx::pipeline_state::scissor_config_state_dirty | rsx::pipeline_state::scissor_setup_clipped);
|
||||||
|
|
||||||
u16 x1, x2, y1, y2;
|
u16 x1, x2, y1, y2;
|
||||||
|
|
||||||
|
@ -1889,7 +1891,7 @@ namespace rsx
|
||||||
|
|
||||||
if (m_graphics_state & rsx::pipeline_state::scissor_setup_invalid)
|
if (m_graphics_state & rsx::pipeline_state::scissor_setup_invalid)
|
||||||
{
|
{
|
||||||
m_graphics_state &= ~rsx::pipeline_state::scissor_setup_invalid;
|
m_graphics_state.clear(rsx::pipeline_state::scissor_setup_invalid);
|
||||||
framebuffer_status_valid = true;
|
framebuffer_status_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1901,10 +1903,12 @@ namespace rsx
|
||||||
|
|
||||||
void thread::prefetch_fragment_program()
|
void thread::prefetch_fragment_program()
|
||||||
{
|
{
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::fragment_program_ucode_dirty))
|
if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_ucode_dirty))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_graphics_state &= ~rsx::pipeline_state::fragment_program_ucode_dirty;
|
m_graphics_state.clear(rsx::pipeline_state::fragment_program_ucode_dirty);
|
||||||
|
|
||||||
// Request for update of fragment constants if the program block is invalidated
|
// Request for update of fragment constants if the program block is invalidated
|
||||||
m_graphics_state |= rsx::pipeline_state::fragment_constants_dirty;
|
m_graphics_state |= rsx::pipeline_state::fragment_constants_dirty;
|
||||||
|
@ -1922,7 +1926,7 @@ namespace rsx
|
||||||
current_fragment_program.texture_state.import(current_fp_texture_state, current_fp_metadata.referenced_textures_mask);
|
current_fragment_program.texture_state.import(current_fp_texture_state, current_fp_metadata.referenced_textures_mask);
|
||||||
current_fragment_program.valid = true;
|
current_fragment_program.valid = true;
|
||||||
|
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::fragment_program_state_dirty))
|
if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_state_dirty))
|
||||||
{
|
{
|
||||||
// Verify current texture state is valid
|
// Verify current texture state is valid
|
||||||
for (u32 textures_ref = current_fp_metadata.referenced_textures_mask, i = 0; textures_ref; textures_ref >>= 1, ++i)
|
for (u32 textures_ref = current_fp_metadata.referenced_textures_mask, i = 0; textures_ref; textures_ref >>= 1, ++i)
|
||||||
|
@ -1937,7 +1941,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::fragment_program_state_dirty) &&
|
if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_state_dirty) &&
|
||||||
(prev_textures_reference_mask != current_fp_metadata.referenced_textures_mask))
|
(prev_textures_reference_mask != current_fp_metadata.referenced_textures_mask))
|
||||||
{
|
{
|
||||||
// If different textures are used, upload their coefficients.
|
// If different textures are used, upload their coefficients.
|
||||||
|
@ -1948,10 +1952,12 @@ namespace rsx
|
||||||
|
|
||||||
void thread::prefetch_vertex_program()
|
void thread::prefetch_vertex_program()
|
||||||
{
|
{
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::vertex_program_ucode_dirty))
|
if (!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_graphics_state &= ~rsx::pipeline_state::vertex_program_ucode_dirty;
|
m_graphics_state.clear(rsx::pipeline_state::vertex_program_ucode_dirty);
|
||||||
|
|
||||||
// Reload transform constants unconditionally for now
|
// Reload transform constants unconditionally for now
|
||||||
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
||||||
|
@ -1969,7 +1975,7 @@ namespace rsx
|
||||||
|
|
||||||
current_vertex_program.texture_state.import(current_vp_texture_state, current_vp_metadata.referenced_textures_mask);
|
current_vertex_program.texture_state.import(current_vp_texture_state, current_vp_metadata.referenced_textures_mask);
|
||||||
|
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::vertex_program_state_dirty))
|
if (!m_graphics_state.test(rsx::pipeline_state::vertex_program_state_dirty))
|
||||||
{
|
{
|
||||||
// Verify current texture state is valid
|
// Verify current texture state is valid
|
||||||
for (u32 textures_ref = current_vp_metadata.referenced_textures_mask, i = 0; textures_ref; textures_ref >>= 1, ++i)
|
for (u32 textures_ref = current_vp_metadata.referenced_textures_mask, i = 0; textures_ref; textures_ref >>= 1, ++i)
|
||||||
|
@ -1993,10 +1999,12 @@ namespace rsx
|
||||||
|
|
||||||
void thread::get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors)
|
void thread::get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors)
|
||||||
{
|
{
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty))
|
if (!m_graphics_state.test(rsx::pipeline_state::vertex_program_dirty))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ensure(!(m_graphics_state & rsx::pipeline_state::vertex_program_ucode_dirty));
|
ensure(!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty));
|
||||||
current_vertex_program.output_mask = rsx::method_registers.vertex_attrib_output_mask();
|
current_vertex_program.output_mask = rsx::method_registers.vertex_attrib_output_mask();
|
||||||
current_vertex_program.ctrl = 0; // Reserved
|
current_vertex_program.ctrl = 0; // Reserved
|
||||||
|
|
||||||
|
@ -2195,12 +2203,14 @@ namespace rsx
|
||||||
|
|
||||||
void thread::get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors)
|
void thread::get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors)
|
||||||
{
|
{
|
||||||
if (!(m_graphics_state & rsx::pipeline_state::fragment_program_dirty))
|
if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_dirty))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ensure(!(m_graphics_state & rsx::pipeline_state::fragment_program_ucode_dirty));
|
ensure(!m_graphics_state.test(rsx::pipeline_state::fragment_program_ucode_dirty));
|
||||||
|
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::fragment_program_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::fragment_program_dirty);
|
||||||
|
|
||||||
current_fragment_program.ctrl = rsx::method_registers.shader_control() & (CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS | CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT);
|
current_fragment_program.ctrl = rsx::method_registers.shader_control() & (CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS | CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT);
|
||||||
current_fragment_program.texcoord_control_mask = rsx::method_registers.texcoord_control_mask();
|
current_fragment_program.texcoord_control_mask = rsx::method_registers.texcoord_control_mask();
|
||||||
|
@ -2428,9 +2438,7 @@ namespace rsx
|
||||||
rsx::method_registers.reset();
|
rsx::method_registers.reset();
|
||||||
check_zcull_status(false);
|
check_zcull_status(false);
|
||||||
nv4097::set_render_mode(this, 0, method_registers.registers[NV4097_SET_RENDER_ENABLE]);
|
nv4097::set_render_mode(this, 0, method_registers.registers[NV4097_SET_RENDER_ENABLE]);
|
||||||
m_graphics_state = pipeline_state::all_dirty;
|
m_graphics_state |= pipeline_state::all_dirty;
|
||||||
m_rtts_dirty = true;
|
|
||||||
m_framebuffer_state_contested = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread::init(u32 ctrlAddress)
|
void thread::init(u32 ctrlAddress)
|
||||||
|
|
|
@ -82,6 +82,10 @@ namespace rsx
|
||||||
|
|
||||||
pipeline_config_dirty = 0x100000, // Generic pipeline configuration changes. Shader peek hint.
|
pipeline_config_dirty = 0x100000, // Generic pipeline configuration changes. Shader peek hint.
|
||||||
|
|
||||||
|
rtt_config_dirty = 0x200000, // Render target configuration changed
|
||||||
|
rtt_config_contested = 0x400000, // Render target configuration is indeterminate
|
||||||
|
texture_cache_state_dirty = 0x800000, // Texture cache state is indeterminate
|
||||||
|
|
||||||
fragment_program_dirty = fragment_program_ucode_dirty | fragment_program_state_dirty,
|
fragment_program_dirty = fragment_program_ucode_dirty | fragment_program_state_dirty,
|
||||||
vertex_program_dirty = vertex_program_ucode_dirty | vertex_program_state_dirty,
|
vertex_program_dirty = vertex_program_ucode_dirty | vertex_program_state_dirty,
|
||||||
invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty,
|
invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty,
|
||||||
|
@ -288,14 +292,12 @@ namespace rsx
|
||||||
|
|
||||||
bool send_event(u64, u64, u64);
|
bool send_event(u64, u64, u64);
|
||||||
|
|
||||||
bool m_rtts_dirty = true;
|
|
||||||
std::array<bool, 16> m_textures_dirty;
|
std::array<bool, 16> m_textures_dirty;
|
||||||
std::array<bool, 4> m_vertex_textures_dirty;
|
std::array<bool, 4> m_vertex_textures_dirty;
|
||||||
bool m_framebuffer_state_contested = false;
|
|
||||||
rsx::framebuffer_creation_context m_current_framebuffer_context = rsx::framebuffer_creation_context::context_draw;
|
rsx::framebuffer_creation_context m_current_framebuffer_context = rsx::framebuffer_creation_context::context_draw;
|
||||||
|
|
||||||
rsx::atomic_bitmask_t<rsx::eng_interrupt_reason> m_eng_interrupt_mask;
|
rsx::atomic_bitmask_t<rsx::eng_interrupt_reason> m_eng_interrupt_mask;
|
||||||
u32 m_graphics_state = 0;
|
rsx::bitmask_t<rsx::pipeline_state> m_graphics_state;
|
||||||
u64 ROP_sync_timestamp = 0;
|
u64 ROP_sync_timestamp = 0;
|
||||||
|
|
||||||
program_hash_util::fragment_program_utils::fragment_program_metadata current_fp_metadata = {};
|
program_hash_util::fragment_program_utils::fragment_program_metadata current_fp_metadata = {};
|
||||||
|
|
|
@ -225,7 +225,7 @@ void VKGSRender::update_draw_state()
|
||||||
bind_viewport();
|
bind_viewport();
|
||||||
|
|
||||||
m_current_command_buffer->flags &= ~vk::command_buffer::cb_reload_dynamic_state;
|
m_current_command_buffer->flags &= ~vk::command_buffer::cb_reload_dynamic_state;
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::polygon_offset_state_dirty | rsx::pipeline_state::depth_bounds_state_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::polygon_offset_state_dirty | rsx::pipeline_state::depth_bounds_state_dirty);
|
||||||
m_frame_stats.setup_time += m_profiler.duration();
|
m_frame_stats.setup_time += m_profiler.duration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1355,7 +1355,7 @@ void VKGSRender::set_viewport()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_current_command_buffer->flags |= vk::command_buffer::cb_reload_dynamic_state;
|
m_current_command_buffer->flags |= vk::command_buffer::cb_reload_dynamic_state;
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::zclip_config_state_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKGSRender::set_scissor(bool clip_viewport)
|
void VKGSRender::set_scissor(bool clip_viewport)
|
||||||
|
@ -1382,7 +1382,7 @@ void VKGSRender::bind_viewport()
|
||||||
m_viewport.maxDepth = rsx::method_registers.clip_max();
|
m_viewport.maxDepth = rsx::method_registers.clip_max();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::zclip_config_state_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &m_viewport);
|
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &m_viewport);
|
||||||
|
@ -1888,7 +1888,7 @@ void VKGSRender::do_local_task(rsx::FIFO::state state)
|
||||||
//This will re-engage locks and break the texture cache if another thread is waiting in access violation handler!
|
//This will re-engage locks and break the texture cache if another thread is waiting in access violation handler!
|
||||||
//Only call when there are no waiters
|
//Only call when there are no waiters
|
||||||
m_texture_cache.do_update();
|
m_texture_cache.do_update();
|
||||||
m_graphics_state &= ~rsx::pipeline_state::framebuffer_reads_dirty;
|
m_graphics_state.clear(rsx::pipeline_state::framebuffer_reads_dirty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1934,7 +1934,7 @@ bool VKGSRender::load_program()
|
||||||
|
|
||||||
get_current_vertex_program(vs_sampler_state);
|
get_current_vertex_program(vs_sampler_state);
|
||||||
|
|
||||||
m_graphics_state &= ~rsx::pipeline_state::invalidate_pipeline_bits;
|
m_graphics_state.clear(rsx::pipeline_state::invalidate_pipeline_bits);
|
||||||
}
|
}
|
||||||
else if (!(m_graphics_state & rsx::pipeline_state::pipeline_config_dirty) &&
|
else if (!(m_graphics_state & rsx::pipeline_state::pipeline_config_dirty) &&
|
||||||
m_program &&
|
m_program &&
|
||||||
|
@ -1978,7 +1978,7 @@ bool VKGSRender::load_program()
|
||||||
|
|
||||||
// Fallthrough
|
// Fallthrough
|
||||||
m_pipeline_properties = properties;
|
m_pipeline_properties = properties;
|
||||||
m_graphics_state &= ~rsx::pipeline_state::pipeline_config_dirty;
|
m_graphics_state.clear(rsx::pipeline_state::pipeline_config_dirty);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2152,7 +2152,7 @@ void VKGSRender::load_program_env()
|
||||||
m_raster_env_ring_info.unmap();
|
m_raster_env_ring_info.unmap();
|
||||||
m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, mem, 128 };
|
m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, mem, 128 };
|
||||||
|
|
||||||
m_graphics_state &= ~(rsx::pipeline_state::polygon_stipple_pattern_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::polygon_stipple_pattern_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_instruction_buffers)
|
if (update_instruction_buffers)
|
||||||
|
@ -2219,9 +2219,13 @@ void VKGSRender::load_program_env()
|
||||||
m_program->bind_buffer({ predicate, 0, 4 }, binding_table.conditional_render_predicate_slot, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_current_frame->descriptor_set);
|
m_program->bind_buffer({ predicate, 0, 4 }, binding_table.conditional_render_predicate_slot, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_current_frame->descriptor_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clear flags
|
// Clear flags
|
||||||
const u32 handled_flags = (rsx::pipeline_state::fragment_state_dirty | rsx::pipeline_state::vertex_state_dirty | rsx::pipeline_state::transform_constants_dirty | rsx::pipeline_state::fragment_constants_dirty | rsx::pipeline_state::fragment_texture_state_dirty);
|
m_graphics_state.clear(
|
||||||
m_graphics_state &= ~handled_flags;
|
rsx::pipeline_state::fragment_state_dirty |
|
||||||
|
rsx::pipeline_state::vertex_state_dirty |
|
||||||
|
rsx::pipeline_state::transform_constants_dirty |
|
||||||
|
rsx::pipeline_state::fragment_constants_dirty |
|
||||||
|
rsx::pipeline_state::fragment_texture_state_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info)
|
void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info)
|
||||||
|
@ -2394,7 +2398,7 @@ void VKGSRender::close_and_submit_command_buffer(vk::fence* pFence, VkSemaphore
|
||||||
void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
||||||
{
|
{
|
||||||
const bool clipped_scissor = (context == rsx::framebuffer_creation_context::context_draw);
|
const bool clipped_scissor = (context == rsx::framebuffer_creation_context::context_draw);
|
||||||
if (m_current_framebuffer_context == context && !m_rtts_dirty && m_draw_fbo)
|
if (m_current_framebuffer_context == context && !m_graphics_state.test(rsx::rtt_config_dirty) && m_draw_fbo)
|
||||||
{
|
{
|
||||||
// Fast path
|
// Fast path
|
||||||
// Framebuffer usage has not changed, framebuffer exists and config regs have not changed
|
// Framebuffer usage has not changed, framebuffer exists and config regs have not changed
|
||||||
|
@ -2402,9 +2406,8 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rtts_dirty = false;
|
m_graphics_state.clear(rsx::rtt_config_dirty | rsx::rtt_config_contested);
|
||||||
framebuffer_status_valid = false;
|
framebuffer_status_valid = false;
|
||||||
m_framebuffer_state_contested = false;
|
|
||||||
|
|
||||||
get_framebuffer_layout(context, m_framebuffer_layout);
|
get_framebuffer_layout(context, m_framebuffer_layout);
|
||||||
if (!framebuffer_status_valid)
|
if (!framebuffer_status_valid)
|
||||||
|
|
|
@ -801,8 +801,8 @@ namespace rsx
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rsx->m_rtts_dirty = true;
|
rsx->m_graphics_state.set(rtt_config_dirty);
|
||||||
rsx->m_framebuffer_state_contested = false;
|
rsx->m_graphics_state.clear(rtt_config_contested);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_surface_format(thread* rsx, u32 reg, u32 arg)
|
void set_surface_format(thread* rsx, u32 reg, u32 arg)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue