mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
rsx: Fix depth clipping
- Fix special case where n=f making (f-n) = 0 - Dynamically update depth range by setting dirty bits - Fix depth bounds when n=f and bounds test is disabled
This commit is contained in:
parent
dc465df3bc
commit
6380e67af9
@ -576,19 +576,34 @@ namespace glsl
|
||||
if (props.domain == glsl::program_domain::glsl_vertex_program && props.emulate_zclip_transform)
|
||||
{
|
||||
OS <<
|
||||
"vec4 apply_zclip_xform(const in vec4 pos, const in float near_plane, const in float far_plane)\n"
|
||||
"double rcp_precise(double x)\n"
|
||||
"{\n"
|
||||
" float d = pos.z / pos.w;\n";
|
||||
" double scaled = x * 0.0009765625;\n"
|
||||
" double inv = 1.0 / scaled;\n"
|
||||
" return inv * 0.0009765625;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec4 apply_zclip_xform(const in vec4 pos, const in float near_plane, const in float far_plane)\n"
|
||||
"{\n";
|
||||
|
||||
if (!props.emulate_depth_clip_only)
|
||||
{
|
||||
OS <<
|
||||
" float d = float(pos.z * rcp_precise(pos.w));\n"
|
||||
" if (d < 0.f && d >= near_plane)\n"
|
||||
" d = 0.f;\n" //force clamp negative values
|
||||
" {\n"
|
||||
" // Clamp\n"
|
||||
" d = 0.f;\n"
|
||||
" }\n"
|
||||
" else if (d > 1.f && d <= far_plane)\n"
|
||||
" {\n"
|
||||
" // Compress Z and store towards highest end of the range\n"
|
||||
" d = min(1., 0.99 + (0.01 * (pos.z - near_plane) / (far_plane - near_plane)));\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" return pos; //d = (0.99 * d);\n" //range compression for normal values is disabled until a solution to ops comparing z is found
|
||||
" {\n"
|
||||
" return pos;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return vec4(pos.x, pos.y, d * pos.w, pos.w);\n";
|
||||
}
|
||||
@ -597,10 +612,18 @@ namespace glsl
|
||||
// Technically the depth value here is the 'final' depth that should be stored in the Z buffer.
|
||||
// Forward mapping eqn is d' = d * (f - n) + n, where d' is the stored Z value (this) and d is the normalized API value.
|
||||
OS <<
|
||||
" double inv_range = double(1.0) / double(far_plane - near_plane);\n"
|
||||
" double new_d = (double(d) - double(near_plane)) * inv_range;\n"
|
||||
"\n"
|
||||
" return vec4(pos.x, pos.y, float(new_d * pos.w), pos.w);\n";
|
||||
" if (far_plane != 0.0)\n"
|
||||
" {\n"
|
||||
" double z_range = (far_plane > near_plane)? (far_plane - near_plane) : far_plane;\n"
|
||||
" double inv_range = rcp_precise(z_range);\n"
|
||||
" float d = float(pos.z * rcp_precise(pos.w));\n"
|
||||
" float new_d = (d - near_plane) * float(inv_range);\n"
|
||||
" return vec4(pos.x, pos.y, (new_d * pos.w), pos.w);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" return pos;\n" // Only values where Z=0 can ever pass this clip
|
||||
" }\n";
|
||||
}
|
||||
|
||||
OS <<
|
||||
|
@ -257,15 +257,15 @@ void GLGSRender::update_draw_state()
|
||||
//NV4097_SET_TWO_SIDE_LIGHT_EN
|
||||
//NV4097_SET_FLAT_SHADE_OP
|
||||
//NV4097_SET_EDGE_FLAG
|
||||
|
||||
|
||||
|
||||
//NV4097_SET_COLOR_KEY_COLOR
|
||||
//NV4097_SET_SHADER_CONTROL
|
||||
//NV4097_SET_ZMIN_MAX_CONTROL
|
||||
//NV4097_SET_ANTI_ALIASING_CONTROL
|
||||
//NV4097_SET_CLIP_ID_TEST_ENABLE
|
||||
|
||||
// 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_frame_stats.setup_time += m_profiler.duration();
|
||||
}
|
||||
|
||||
|
@ -78,14 +78,16 @@ namespace rsx
|
||||
fragment_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
|
||||
zclip_config_state_dirty = 0x400, // Viewport Z clip changed
|
||||
|
||||
scissor_setup_invalid = 0x400, // Scissor configuration is broken
|
||||
scissor_setup_clipped = 0x800, // Scissor region is cropped by viewport constraint
|
||||
scissor_setup_invalid = 0x800, // Scissor configuration is broken
|
||||
scissor_setup_clipped = 0x1000, // Scissor region is cropped by viewport constraint
|
||||
|
||||
polygon_stipple_pattern_dirty = 0x1000, // Rasterizer stippling pattern changed
|
||||
line_stipple_pattern_dirty = 0x2000, // Line stippling pattern changed
|
||||
polygon_stipple_pattern_dirty = 0x2000, // Rasterizer stippling pattern changed
|
||||
line_stipple_pattern_dirty = 0x4000, // Line stippling pattern changed
|
||||
|
||||
invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty,
|
||||
invalidate_zclip_bits = vertex_state_dirty | zclip_config_state_dirty,
|
||||
memory_barrier_bits = framebuffer_reads_dirty,
|
||||
all_dirty = ~0u
|
||||
};
|
||||
|
@ -117,8 +117,9 @@ void VKGSRender::update_draw_state()
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds_min = rsx::method_registers.clip_min();
|
||||
bounds_max = rsx::method_registers.clip_max();
|
||||
// Avoid special case where min=max and depth bounds (incorrectly) fails
|
||||
bounds_min = std::min(0.f, rsx::method_registers.clip_min());
|
||||
bounds_max = std::max(1.f, rsx::method_registers.clip_max());
|
||||
}
|
||||
|
||||
if (!m_device->get_unrestricted_depth_range_support())
|
||||
|
@ -974,6 +974,8 @@ void VKGSRender::set_viewport()
|
||||
m_viewport.minDepth = 0.f;
|
||||
m_viewport.maxDepth = 1.f;
|
||||
}
|
||||
|
||||
m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty);
|
||||
}
|
||||
|
||||
void VKGSRender::set_scissor(bool clip_viewport)
|
||||
@ -990,6 +992,17 @@ void VKGSRender::set_scissor(bool clip_viewport)
|
||||
|
||||
void VKGSRender::bind_viewport()
|
||||
{
|
||||
if (m_graphics_state & rsx::pipeline_state::zclip_config_state_dirty)
|
||||
{
|
||||
if (m_device->get_unrestricted_depth_range_support())
|
||||
{
|
||||
m_viewport.minDepth = rsx::method_registers.clip_min();
|
||||
m_viewport.maxDepth = rsx::method_registers.clip_max();
|
||||
}
|
||||
|
||||
m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty);
|
||||
}
|
||||
|
||||
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &m_viewport);
|
||||
vkCmdSetScissor(*m_current_command_buffer, 0, 1, &m_scissor);
|
||||
}
|
||||
|
@ -887,18 +887,6 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<u32 index>
|
||||
struct set_viewport_dirty_bit
|
||||
{
|
||||
static void impl(thread* rsx, u32 _reg, u32 arg)
|
||||
{
|
||||
if (arg != method_registers.register_previous_value)
|
||||
{
|
||||
rsx->m_graphics_state |= rsx::pipeline_state::vertex_state_dirty;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace nv308a
|
||||
@ -3169,8 +3157,8 @@ namespace rsx
|
||||
bind<NV4097_SET_VERTEX_DATA_BASE_INDEX, nv4097::set_index_base_offset>();
|
||||
bind<NV4097_SET_USER_CLIP_PLANE_CONTROL, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||
bind<NV4097_SET_TRANSFORM_BRANCH_BITS, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||
bind<NV4097_SET_CLIP_MIN, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||
bind<NV4097_SET_CLIP_MAX, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||
bind<NV4097_SET_CLIP_MIN, nv4097::notify_state_changed<invalidate_zclip_bits>>();
|
||||
bind<NV4097_SET_CLIP_MAX, nv4097::notify_state_changed<invalidate_zclip_bits>>();
|
||||
bind<NV4097_SET_POINT_SIZE, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||
bind<NV4097_SET_ALPHA_FUNC, nv4097::notify_state_changed<fragment_state_dirty>>();
|
||||
bind<NV4097_SET_ALPHA_REF, nv4097::notify_state_changed<fragment_state_dirty>>();
|
||||
@ -3184,8 +3172,8 @@ namespace rsx
|
||||
bind<NV4097_SET_VIEWPORT_HORIZONTAL, nv4097::notify_state_changed<scissor_config_state_dirty>>();
|
||||
bind<NV4097_SET_VIEWPORT_VERTICAL, nv4097::notify_state_changed<scissor_config_state_dirty>>();
|
||||
bind_array<NV4097_SET_FOG_PARAMS, 1, 2, nv4097::notify_state_changed<fragment_state_dirty>>();
|
||||
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_array<NV4097_SET_VIEWPORT_SCALE, 1, 3, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||
bind_array<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||
bind<NV4097_SET_INDEX_ARRAY_DMA, nv4097::check_index_array_dma>();
|
||||
bind<NV4097_SET_BLEND_EQUATION, nv4097::set_blend_equation>();
|
||||
bind<NV4097_SET_BLEND_FUNC_SFACTOR, nv4097::set_blend_factor>();
|
||||
|
Loading…
Reference in New Issue
Block a user