mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
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:
parent
1b140c8e97
commit
b5a2f0df68
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>();
|
||||
|
Loading…
Reference in New Issue
Block a user