rsx: Implement separate viewport raster clipping

- Merge viewport raster window and scissor into one clipping region
- Viewport raster clip is different from viewport geometry clipping in
hardware as the latter is configurable separately
This commit is contained in:
kd-11 2019-07-18 16:50:21 +03:00 committed by kd-11
parent 1b140c8e97
commit b5a2f0df68
7 changed files with 69 additions and 69 deletions

View File

@ -476,7 +476,7 @@ void D3D12GSRender::end()
};
get_current_resource_storage().command_list->RSSetViewports(1, &viewport);
get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(),
get_current_resource_storage().command_list->RSSetScissorRects(1, &::get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(),
rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(rsx::method_registers.current_draw_clause.primitive));

View File

@ -125,12 +125,12 @@ void D3D12GSRender::clear_surface(u32 arg)
u32 clear_depth = rsx::method_registers.z_clear_value(depth_format == rsx::surface_depth_format::z24s8);
u32 max_depth_value = get_max_depth_value(depth_format);
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0,
1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
1, &::get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
}
if (arg & 0x2)
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers.stencil_clear_value()),
1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
1, &::get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
}
if (arg & 0xF0)
@ -147,7 +147,7 @@ void D3D12GSRender::clear_surface(u32 arg)
};
for (unsigned i = 0; i < rtt_index; i++)
get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, m_descriptor_stride_rtv), clear_color.data(),
1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
1, &::get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
}
std::chrono::time_point<steady_clock> end_duration = steady_clock::now();

View File

@ -651,43 +651,14 @@ void GLGSRender::set_viewport()
void GLGSRender::set_scissor()
{
if (m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty)
areau scissor;
if (get_scissor(scissor))
{
// Optimistic that the new config will allow us to render
framebuffer_status_valid = true;
// 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.x1, scissor.y1, scissor.width(), scissor.height());
gl_state.enable(GL_TRUE, GL_SCISSOR_TEST);
}
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_setup_invalid);
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
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
glScissor(scissor_x, scissor_y, scissor_w, scissor_h);
gl_state.enable(GL_TRUE, GL_SCISSOR_TEST);
}
void GLGSRender::on_init_thread()

View File

@ -1293,6 +1293,56 @@ namespace rsx
return layout;
}
bool thread::get_scissor(areau& region)
{
if (!(m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty))
{
// Nothing to do
return false;
}
m_graphics_state &= ~rsx::pipeline_state::scissor_config_state_dirty;
u16 scissor_x = rsx::method_registers.scissor_origin_x();
u16 scissor_w = rsx::method_registers.scissor_width();
u16 scissor_y = rsx::method_registers.scissor_origin_y();
u16 scissor_h = rsx::method_registers.scissor_height();
u16 raster_x = rsx::method_registers.viewport_origin_x();
u16 raster_w = rsx::method_registers.viewport_width();
u16 raster_y = rsx::method_registers.viewport_origin_y();
u16 raster_h = rsx::method_registers.viewport_height();
// Get the minimum area between these two
u16 x1 = std::max(scissor_x, raster_x);
u16 y1 = std::max(scissor_y, raster_y);
u16 x2 = std::min(scissor_x + scissor_w, raster_x + raster_w);
u16 y2 = std::min(scissor_y + scissor_h, raster_y + raster_h);
if (x2 <= x1 ||
y2 <= y1 ||
x1 >= rsx::method_registers.window_clip_horizontal() ||
y1 >= rsx::method_registers.window_clip_vertical())
{
m_graphics_state |= rsx::pipeline_state::scissor_setup_invalid;
framebuffer_status_valid = false;
return false;
}
if (m_graphics_state & rsx::pipeline_state::scissor_setup_invalid)
{
m_graphics_state &= ~rsx::pipeline_state::scissor_setup_invalid;
framebuffer_status_valid = true;
}
region.x1 = rsx::apply_resolution_scale(x1, false);
region.x2 = rsx::apply_resolution_scale(x2, true);
region.y1 = rsx::apply_resolution_scale(y1, false);
region.y2 = rsx::apply_resolution_scale(y2, true);
return true;
}
void thread::get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors, bool skip_textures, bool skip_vertex_inputs)
{
if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty))

View File

@ -520,6 +520,7 @@ namespace rsx
u32 get_zeta_surface_address() const;
framebuffer_layout get_framebuffer_layout(rsx::framebuffer_creation_context context);
bool get_scissor(areau& region);
/**
* Analyze vertex inputs and group all interleaved blocks

View File

@ -1796,37 +1796,13 @@ void VKGSRender::set_viewport()
void VKGSRender::set_scissor()
{
if (m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty)
areau scissor;
if (get_scissor(scissor))
{
// 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_setup_invalid);
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);
m_scissor.extent.height = scissor_h;
m_scissor.extent.width = scissor_w;
m_scissor.offset.x = scissor_x;
m_scissor.offset.y = scissor_y;
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;
}
m_scissor.extent.height = scissor.height();
m_scissor.extent.width = scissor.width();
m_scissor.offset.x = scissor.x1;
m_scissor.offset.y = scissor.y1;
}
}

View File

@ -2790,6 +2790,8 @@ namespace rsx
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<NV4097_SET_VIEWPORT_HORIZONTAL, nv4097::set_scissor_dirty_bit>();
bind<NV4097_SET_VIEWPORT_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>();