mirror of https://github.com/RPCS3/rpcs3.git
rsx: Critical pipeline fixes
- Fix scissor and viewport binding behavior - Fixes recovery if empty scissor is specified and then 'fixed' later - Optimizes state binding a bit
This commit is contained in:
parent
1ad76ad331
commit
54ec363e88
|
@ -640,29 +640,49 @@ void GLGSRender::end()
|
|||
|
||||
void GLGSRender::set_viewport()
|
||||
{
|
||||
//NOTE: scale offset matrix already contains the viewport transformation
|
||||
// NOTE: scale offset matrix already contains the viewport transformation
|
||||
const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true);
|
||||
const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true);
|
||||
glViewport(0, 0, clip_width, clip_height);
|
||||
}
|
||||
|
||||
void GLGSRender::set_scissor()
|
||||
{
|
||||
if (m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty)
|
||||
{
|
||||
// Optimistic that the new config will allow us to render
|
||||
framebuffer_status_valid = true;
|
||||
}
|
||||
else if (!(m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty))
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
m_graphics_state &= ~(rsx::pipeline_state::scissor_config_state_dirty | rsx::pipeline_state::scissor_config_state_dirty);
|
||||
|
||||
const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true);
|
||||
const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true);
|
||||
|
||||
u16 scissor_x = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_x(), false);
|
||||
u16 scissor_w = rsx::apply_resolution_scale(rsx::method_registers.scissor_width(), true);
|
||||
u16 scissor_y = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_y(), false);
|
||||
u16 scissor_h = rsx::apply_resolution_scale(rsx::method_registers.scissor_height(), true);
|
||||
|
||||
//Do not bother drawing anything if output is zero sized
|
||||
//TODO: Clip scissor region
|
||||
// Do not bother drawing anything if output is zero sized
|
||||
// TODO: Clip scissor region
|
||||
if (scissor_x >= clip_width || scissor_y >= clip_height || scissor_w == 0 || scissor_h == 0)
|
||||
{
|
||||
if (!g_cfg.video.strict_rendering_mode)
|
||||
{
|
||||
m_graphics_state |= rsx::pipeline_state::scissor_setup_invalid;
|
||||
framebuffer_status_valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: window origin does not affect scissor region (probably only affects viewport matrix; already applied)
|
||||
//See LIMBO [NPUB-30373] which uses shader window origin = top
|
||||
// NOTE: window origin does not affect scissor region (probably only affects viewport matrix; already applied)
|
||||
// See LIMBO [NPUB-30373] which uses shader window origin = top
|
||||
glScissor(scissor_x, scissor_y, scissor_w, scissor_h);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
|
|
@ -371,6 +371,7 @@ private:
|
|||
public:
|
||||
void read_buffers();
|
||||
void set_viewport();
|
||||
void set_scissor();
|
||||
|
||||
work_item& post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data);
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
|
||||
if (m_draw_fbo && !m_rtts_dirty)
|
||||
{
|
||||
set_viewport();
|
||||
set_scissor();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -371,6 +371,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
|
|||
|
||||
check_zcull_status(true);
|
||||
set_viewport();
|
||||
set_scissor();
|
||||
|
||||
m_gl_texture_cache.clear_ro_tex_invalidate_intr();
|
||||
|
||||
|
|
|
@ -98,7 +98,10 @@ namespace rsx
|
|||
fragment_constants_dirty = 0x20, // Fragment constants changed
|
||||
framebuffer_reads_dirty = 0x40, // Framebuffer contents changed
|
||||
fragment_texture_state_dirty = 0x80, // Fragment texture parameters changed
|
||||
vertex_texture_state_dirty = 0x80, // Fragment texture parameters changed
|
||||
vertex_texture_state_dirty = 0x100, // Fragment texture parameters changed
|
||||
scissor_config_state_dirty = 0x200, // Scissor region changed
|
||||
|
||||
scissor_setup_invalid = 0x400, // Scissor configuration is broken
|
||||
|
||||
invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty,
|
||||
memory_barrier_bits = framebuffer_reads_dirty,
|
||||
|
|
|
@ -1121,7 +1121,7 @@ void VKGSRender::update_draw_state()
|
|||
vkCmdSetDepthBounds(*m_current_command_buffer, 0.f, 1.f);
|
||||
}
|
||||
|
||||
set_viewport();
|
||||
bind_viewport();
|
||||
|
||||
//TODO: Set up other render-state parameters into the program pipeline
|
||||
|
||||
|
@ -1678,40 +1678,58 @@ void VKGSRender::set_viewport()
|
|||
{
|
||||
const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true);
|
||||
const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true);
|
||||
|
||||
//NOTE: The scale_offset matrix already has viewport matrix factored in
|
||||
m_viewport.x = 0;
|
||||
m_viewport.y = 0;
|
||||
m_viewport.width = clip_width;
|
||||
m_viewport.height = clip_height;
|
||||
m_viewport.minDepth = 0.f;
|
||||
m_viewport.maxDepth = 1.f;
|
||||
}
|
||||
|
||||
void VKGSRender::set_scissor()
|
||||
{
|
||||
if (m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty)
|
||||
{
|
||||
// Optimistic that the new config will allow us to render
|
||||
framebuffer_status_valid = true;
|
||||
}
|
||||
else if (!(m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty))
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
m_graphics_state &= ~(rsx::pipeline_state::scissor_config_state_dirty | rsx::pipeline_state::scissor_config_state_dirty);
|
||||
|
||||
u16 scissor_x = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_x(), false);
|
||||
u16 scissor_w = rsx::apply_resolution_scale(rsx::method_registers.scissor_width(), true);
|
||||
u16 scissor_y = rsx::apply_resolution_scale(rsx::method_registers.scissor_origin_y(), false);
|
||||
u16 scissor_h = rsx::apply_resolution_scale(rsx::method_registers.scissor_height(), true);
|
||||
|
||||
//NOTE: The scale_offset matrix already has viewport matrix factored in
|
||||
VkViewport viewport = {};
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = clip_width;
|
||||
viewport.height = clip_height;
|
||||
viewport.minDepth = 0.f;
|
||||
viewport.maxDepth = 1.f;
|
||||
m_scissor.extent.height = scissor_h;
|
||||
m_scissor.extent.width = scissor_w;
|
||||
m_scissor.offset.x = scissor_x;
|
||||
m_scissor.offset.y = scissor_y;
|
||||
|
||||
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor = {};
|
||||
scissor.extent.height = scissor_h;
|
||||
scissor.extent.width = scissor_w;
|
||||
scissor.offset.x = scissor_x;
|
||||
scissor.offset.y = scissor_y;
|
||||
|
||||
vkCmdSetScissor(*m_current_command_buffer, 0, 1, &scissor);
|
||||
|
||||
if (scissor_x >= viewport.width || scissor_y >= viewport.height || scissor_w == 0 || scissor_h == 0)
|
||||
if (scissor_x >= m_viewport.width || scissor_y >= m_viewport.height || scissor_w == 0 || scissor_h == 0)
|
||||
{
|
||||
if (!g_cfg.video.strict_rendering_mode)
|
||||
{
|
||||
m_graphics_state |= rsx::pipeline_state::scissor_setup_invalid;
|
||||
framebuffer_status_valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VKGSRender::bind_viewport()
|
||||
{
|
||||
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &m_viewport);
|
||||
vkCmdSetScissor(*m_current_command_buffer, 0, 1, &m_scissor);
|
||||
}
|
||||
|
||||
void VKGSRender::on_init_thread()
|
||||
{
|
||||
if (m_device == VK_NULL_HANDLE)
|
||||
|
@ -2743,7 +2761,10 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||
}
|
||||
|
||||
if (m_draw_fbo && !m_rtts_dirty)
|
||||
{
|
||||
set_scissor();
|
||||
return;
|
||||
}
|
||||
|
||||
m_rtts_dirty = false;
|
||||
framebuffer_status_valid = false;
|
||||
|
@ -2946,6 +2967,9 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
|
|||
m_draw_fbo.reset(new vk::framebuffer_holder(*m_device, current_render_pass, fbo_width, fbo_height, std::move(fbo_images)));
|
||||
}
|
||||
|
||||
set_viewport();
|
||||
set_scissor();
|
||||
|
||||
check_zcull_status(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -369,6 +369,9 @@ private:
|
|||
u32 m_client_width = 0;
|
||||
u32 m_client_height = 0;
|
||||
|
||||
VkViewport m_viewport{};
|
||||
VkRect2D m_scissor{};
|
||||
|
||||
// Draw call stats
|
||||
u32 m_draw_calls = 0;
|
||||
|
||||
|
@ -432,6 +435,8 @@ public:
|
|||
void read_buffers();
|
||||
void write_buffers();
|
||||
void set_viewport();
|
||||
void set_scissor();
|
||||
void bind_viewport();
|
||||
|
||||
void sync_hint(rsx::FIFO_hint hint) override;
|
||||
|
||||
|
|
|
@ -650,7 +650,7 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
void set_vertex_env_dirty_bit(thread* rsx, u32 reg, u32 arg)
|
||||
void set_vertex_env_dirty_bit(thread* rsx, u32, u32 arg)
|
||||
{
|
||||
if (arg != method_registers.register_previous_value)
|
||||
{
|
||||
|
@ -658,7 +658,7 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
void set_fragment_env_dirty_bit(thread* rsx, u32 reg, u32 arg)
|
||||
void set_fragment_env_dirty_bit(thread* rsx, u32, u32 arg)
|
||||
{
|
||||
if (arg != method_registers.register_previous_value)
|
||||
{
|
||||
|
@ -666,6 +666,14 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
void set_scissor_dirty_bit(thread* rsx, u32 reg, u32 arg)
|
||||
{
|
||||
if (arg != method_registers.register_previous_value)
|
||||
{
|
||||
rsx->m_graphics_state |= rsx::pipeline_state::scissor_config_state_dirty;
|
||||
}
|
||||
}
|
||||
|
||||
template<u32 index>
|
||||
struct set_texture_dirty_bit
|
||||
{
|
||||
|
@ -2729,6 +2737,8 @@ namespace rsx
|
|||
bind<NV4097_SET_SHADER_PACKER, nv4097::set_ROP_state_dirty_bit>();
|
||||
bind<NV4097_SET_SHADER_WINDOW, nv4097::set_ROP_state_dirty_bit>();
|
||||
bind<NV4097_SET_FOG_MODE, nv4097::set_ROP_state_dirty_bit>();
|
||||
bind<NV4097_SET_SCISSOR_HORIZONTAL, nv4097::set_scissor_dirty_bit>();
|
||||
bind<NV4097_SET_SCISSOR_VERTICAL, nv4097::set_scissor_dirty_bit>();
|
||||
bind_array<NV4097_SET_FOG_PARAMS, 1, 2, nv4097::set_ROP_state_dirty_bit>();
|
||||
bind_range<NV4097_SET_VIEWPORT_SCALE, 1, 3, nv4097::set_viewport_dirty_bit>();
|
||||
bind_range<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::set_viewport_dirty_bit>();
|
||||
|
|
Loading…
Reference in New Issue