mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 17:11:23 +00: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)
|
if (props.domain == glsl::program_domain::glsl_vertex_program && props.emulate_zclip_transform)
|
||||||
{
|
{
|
||||||
OS <<
|
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"
|
"{\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)
|
if (!props.emulate_depth_clip_only)
|
||||||
{
|
{
|
||||||
OS <<
|
OS <<
|
||||||
|
" float d = float(pos.z * rcp_precise(pos.w));\n"
|
||||||
" if (d < 0.f && d >= near_plane)\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"
|
" 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"
|
" d = min(1., 0.99 + (0.01 * (pos.z - near_plane) / (far_plane - near_plane)));\n"
|
||||||
|
" }\n"
|
||||||
" else\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"
|
"\n"
|
||||||
" return vec4(pos.x, pos.y, d * pos.w, pos.w);\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.
|
// 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.
|
// 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 <<
|
OS <<
|
||||||
" double inv_range = double(1.0) / double(far_plane - near_plane);\n"
|
" if (far_plane != 0.0)\n"
|
||||||
" double new_d = (double(d) - double(near_plane)) * inv_range;\n"
|
" {\n"
|
||||||
"\n"
|
" double z_range = (far_plane > near_plane)? (far_plane - near_plane) : far_plane;\n"
|
||||||
" return vec4(pos.x, pos.y, float(new_d * pos.w), pos.w);\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 <<
|
OS <<
|
||||||
|
@ -257,15 +257,15 @@ void GLGSRender::update_draw_state()
|
|||||||
//NV4097_SET_TWO_SIDE_LIGHT_EN
|
//NV4097_SET_TWO_SIDE_LIGHT_EN
|
||||||
//NV4097_SET_FLAT_SHADE_OP
|
//NV4097_SET_FLAT_SHADE_OP
|
||||||
//NV4097_SET_EDGE_FLAG
|
//NV4097_SET_EDGE_FLAG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//NV4097_SET_COLOR_KEY_COLOR
|
//NV4097_SET_COLOR_KEY_COLOR
|
||||||
//NV4097_SET_SHADER_CONTROL
|
//NV4097_SET_SHADER_CONTROL
|
||||||
//NV4097_SET_ZMIN_MAX_CONTROL
|
//NV4097_SET_ZMIN_MAX_CONTROL
|
||||||
//NV4097_SET_ANTI_ALIASING_CONTROL
|
//NV4097_SET_ANTI_ALIASING_CONTROL
|
||||||
//NV4097_SET_CLIP_ID_TEST_ENABLE
|
//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();
|
m_frame_stats.setup_time += m_profiler.duration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,14 +78,16 @@ namespace rsx
|
|||||||
fragment_texture_state_dirty = 0x80, // Fragment texture parameters changed
|
fragment_texture_state_dirty = 0x80, // Fragment texture parameters changed
|
||||||
vertex_texture_state_dirty = 0x100, // Fragment texture parameters changed
|
vertex_texture_state_dirty = 0x100, // Fragment texture parameters changed
|
||||||
scissor_config_state_dirty = 0x200, // Scissor region 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_invalid = 0x800, // Scissor configuration is broken
|
||||||
scissor_setup_clipped = 0x800, // Scissor region is cropped by viewport constraint
|
scissor_setup_clipped = 0x1000, // Scissor region is cropped by viewport constraint
|
||||||
|
|
||||||
polygon_stipple_pattern_dirty = 0x1000, // Rasterizer stippling pattern changed
|
polygon_stipple_pattern_dirty = 0x2000, // Rasterizer stippling pattern changed
|
||||||
line_stipple_pattern_dirty = 0x2000, // Line stippling pattern changed
|
line_stipple_pattern_dirty = 0x4000, // Line stippling pattern changed
|
||||||
|
|
||||||
invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty,
|
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,
|
memory_barrier_bits = framebuffer_reads_dirty,
|
||||||
all_dirty = ~0u
|
all_dirty = ~0u
|
||||||
};
|
};
|
||||||
|
@ -117,8 +117,9 @@ void VKGSRender::update_draw_state()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bounds_min = rsx::method_registers.clip_min();
|
// Avoid special case where min=max and depth bounds (incorrectly) fails
|
||||||
bounds_max = rsx::method_registers.clip_max();
|
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())
|
if (!m_device->get_unrestricted_depth_range_support())
|
||||||
|
@ -974,6 +974,8 @@ void VKGSRender::set_viewport()
|
|||||||
m_viewport.minDepth = 0.f;
|
m_viewport.minDepth = 0.f;
|
||||||
m_viewport.maxDepth = 1.f;
|
m_viewport.maxDepth = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKGSRender::set_scissor(bool clip_viewport)
|
void VKGSRender::set_scissor(bool clip_viewport)
|
||||||
@ -990,6 +992,17 @@ void VKGSRender::set_scissor(bool clip_viewport)
|
|||||||
|
|
||||||
void VKGSRender::bind_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);
|
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &m_viewport);
|
||||||
vkCmdSetScissor(*m_current_command_buffer, 0, 1, &m_scissor);
|
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
|
namespace nv308a
|
||||||
@ -3169,8 +3157,8 @@ namespace rsx
|
|||||||
bind<NV4097_SET_VERTEX_DATA_BASE_INDEX, nv4097::set_index_base_offset>();
|
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_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_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_MIN, nv4097::notify_state_changed<invalidate_zclip_bits>>();
|
||||||
bind<NV4097_SET_CLIP_MAX, nv4097::notify_state_changed<vertex_state_dirty>>();
|
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_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_FUNC, nv4097::notify_state_changed<fragment_state_dirty>>();
|
||||||
bind<NV4097_SET_ALPHA_REF, 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_HORIZONTAL, nv4097::notify_state_changed<scissor_config_state_dirty>>();
|
||||||
bind<NV4097_SET_VIEWPORT_VERTICAL, 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_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_array<NV4097_SET_VIEWPORT_SCALE, 1, 3, nv4097::notify_state_changed<vertex_state_dirty>>();
|
||||||
bind_range<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::set_viewport_dirty_bit>();
|
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_INDEX_ARRAY_DMA, nv4097::check_index_array_dma>();
|
||||||
bind<NV4097_SET_BLEND_EQUATION, nv4097::set_blend_equation>();
|
bind<NV4097_SET_BLEND_EQUATION, nv4097::set_blend_equation>();
|
||||||
bind<NV4097_SET_BLEND_FUNC_SFACTOR, nv4097::set_blend_factor>();
|
bind<NV4097_SET_BLEND_FUNC_SFACTOR, nv4097::set_blend_factor>();
|
||||||
|
Loading…
Reference in New Issue
Block a user