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:
kd-11 2018-10-28 15:20:53 +03:00 committed by kd-11
parent 1ad76ad331
commit 54ec363e88
7 changed files with 93 additions and 29 deletions

View File

@ -644,6 +644,25 @@ void GLGSRender::set_viewport()
const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true); 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); const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true);
glViewport(0, 0, clip_width, clip_height); 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_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_w = rsx::apply_resolution_scale(rsx::method_registers.scissor_width(), true);
@ -656,6 +675,7 @@ void GLGSRender::set_viewport()
{ {
if (!g_cfg.video.strict_rendering_mode) if (!g_cfg.video.strict_rendering_mode)
{ {
m_graphics_state |= rsx::pipeline_state::scissor_setup_invalid;
framebuffer_status_valid = false; framebuffer_status_valid = false;
return; return;
} }

View File

@ -371,6 +371,7 @@ private:
public: public:
void read_buffers(); void read_buffers();
void set_viewport(); void set_viewport();
void set_scissor();
work_item& post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data); work_item& post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data);

View File

@ -181,7 +181,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
if (m_draw_fbo && !m_rtts_dirty) if (m_draw_fbo && !m_rtts_dirty)
{ {
set_viewport(); set_scissor();
return; return;
} }
@ -371,6 +371,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk
check_zcull_status(true); check_zcull_status(true);
set_viewport(); set_viewport();
set_scissor();
m_gl_texture_cache.clear_ro_tex_invalidate_intr(); m_gl_texture_cache.clear_ro_tex_invalidate_intr();

View File

@ -98,7 +98,10 @@ namespace rsx
fragment_constants_dirty = 0x20, // Fragment constants changed fragment_constants_dirty = 0x20, // Fragment constants changed
framebuffer_reads_dirty = 0x40, // Framebuffer contents changed framebuffer_reads_dirty = 0x40, // Framebuffer contents changed
fragment_texture_state_dirty = 0x80, // Fragment texture parameters 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, invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty,
memory_barrier_bits = framebuffer_reads_dirty, memory_barrier_bits = framebuffer_reads_dirty,

View File

@ -1121,7 +1121,7 @@ void VKGSRender::update_draw_state()
vkCmdSetDepthBounds(*m_current_command_buffer, 0.f, 1.f); vkCmdSetDepthBounds(*m_current_command_buffer, 0.f, 1.f);
} }
set_viewport(); bind_viewport();
//TODO: Set up other render-state parameters into the program pipeline //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_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); 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_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_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_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); u16 scissor_h = rsx::apply_resolution_scale(rsx::method_registers.scissor_height(), true);
//NOTE: The scale_offset matrix already has viewport matrix factored in m_scissor.extent.height = scissor_h;
VkViewport viewport = {}; m_scissor.extent.width = scissor_w;
viewport.x = 0; m_scissor.offset.x = scissor_x;
viewport.y = 0; m_scissor.offset.y = scissor_y;
viewport.width = clip_width;
viewport.height = clip_height;
viewport.minDepth = 0.f;
viewport.maxDepth = 1.f;
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &viewport); if (scissor_x >= m_viewport.width || scissor_y >= m_viewport.height || scissor_w == 0 || scissor_h == 0)
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 (!g_cfg.video.strict_rendering_mode) if (!g_cfg.video.strict_rendering_mode)
{ {
m_graphics_state |= rsx::pipeline_state::scissor_setup_invalid;
framebuffer_status_valid = false; framebuffer_status_valid = false;
return; 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() void VKGSRender::on_init_thread()
{ {
if (m_device == VK_NULL_HANDLE) 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) if (m_draw_fbo && !m_rtts_dirty)
{
set_scissor();
return; return;
}
m_rtts_dirty = false; m_rtts_dirty = false;
framebuffer_status_valid = 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))); 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); check_zcull_status(true);
} }

View File

@ -369,6 +369,9 @@ private:
u32 m_client_width = 0; u32 m_client_width = 0;
u32 m_client_height = 0; u32 m_client_height = 0;
VkViewport m_viewport{};
VkRect2D m_scissor{};
// Draw call stats // Draw call stats
u32 m_draw_calls = 0; u32 m_draw_calls = 0;
@ -432,6 +435,8 @@ public:
void read_buffers(); void read_buffers();
void write_buffers(); void write_buffers();
void set_viewport(); void set_viewport();
void set_scissor();
void bind_viewport();
void sync_hint(rsx::FIFO_hint hint) override; void sync_hint(rsx::FIFO_hint hint) override;

View File

@ -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) 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) 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> template<u32 index>
struct set_texture_dirty_bit 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_PACKER, nv4097::set_ROP_state_dirty_bit>();
bind<NV4097_SET_SHADER_WINDOW, 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_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_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_SCALE, 1, 3, nv4097::set_viewport_dirty_bit>();
bind_range<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::set_viewport_dirty_bit>(); bind_range<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::set_viewport_dirty_bit>();