aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner.de@gmail.com>2019-01-30 00:04:46 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-02-27 13:55:09 -0500
commitd63716658ac16c515d1223a9fbf5edbf76b1b333 (patch)
treeab2c15af7830f1ce4080028c6e2abca5e75d4415
parenta213c2c7e235cfc0e0a161a558f7fdf2fb3a624a (diff)
drm/amd/display: Use vrr friendly pageflip throttling in DC.
In VRR mode, keep track of the vblank count of the last completed pageflip in amdgpu_crtc->last_flip_vblank, as recorded in the pageflip completion handler after each completed flip. Use that count to prevent mmio programming a new pageflip within the same vblank in which the last pageflip completed, iow. to throttle pageflips to at most one flip per video frame, while at the same time allowing to request a flip not only before start of vblank, but also anywhere within vblank. The old logic did the same, and made sense for regular fixed refresh rate flipping, but in vrr mode it prevents requesting a flip anywhere inside the possibly huge vblank, thereby reducing framerate in vrr mode instead of improving it, by delaying a slightly delayed flip requests up to a maximum vblank duration + 1 scanout duration. This would limit VRR usefulness to only help applications with a very high GPU demand, which can submit the flip request before start of vblank, but then have to wait long for fences to complete. With this method a flip can be both requested and - after fences have completed - executed, ie. it doesn't matter if the request (amdgpu_dm_do_flip()) gets delayed until deep into the extended vblank due to cpu execution delays. This also allows clients which want to regulate framerate within the vrr range a much more fine-grained control of flip timing, a feature that might be useful for video playback, and is very useful for neuroscience/vision research applications. In regular non-VRR mode, retain the old flip submission behavior. This to keep flip scheduling for fullscreen X11/GLX OpenGL clients intact, if they use the GLX_OML_sync_control extensions glXSwapBufferMscOML(, ..., target_msc,...) function with a specific target_msc target vblank count. glXSwapBuffersMscOML() or DRI3/Present PresentPixmap() will not flip at the proper target_msc for a non-zero target_msc if VRR mode is active with this patch. They'd often flip one frame too early. However, this limitation should not matter much in VRR mode, as scheduling based on vblank counts is pretty futile/unusable under variable refresh duration anyway, so no real extra harm is done. Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> Cc: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Cc: Harry Wentland <harry.wentland@amd.com> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Michel Dänzer <michel@daenzer.net> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c27
2 files changed, 24 insertions, 4 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index aadd0fa42e43..3aa42c64484a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -405,6 +405,7 @@ struct amdgpu_crtc {
405 struct amdgpu_flip_work *pflip_works; 405 struct amdgpu_flip_work *pflip_works;
406 enum amdgpu_flip_status pflip_status; 406 enum amdgpu_flip_status pflip_status;
407 int deferred_flip_completion; 407 int deferred_flip_completion;
408 u64 last_flip_vblank;
408 /* pll sharing */ 409 /* pll sharing */
409 struct amdgpu_atom_ss ss; 410 struct amdgpu_atom_ss ss;
410 bool ss_enabled; 411 bool ss_enabled;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5296b8f3e0ab..636d14a60952 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -303,12 +303,11 @@ static void dm_pflip_high_irq(void *interrupt_params)
303 return; 303 return;
304 } 304 }
305 305
306 /* Update to correct count(s) if racing with vblank irq */
307 amdgpu_crtc->last_flip_vblank = drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
306 308
307 /* wake up userspace */ 309 /* wake up userspace */
308 if (amdgpu_crtc->event) { 310 if (amdgpu_crtc->event) {
309 /* Update to correct count(s) if racing with vblank irq */
310 drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
311
312 drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); 311 drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event);
313 312
314 /* page flip completed. clean up */ 313 /* page flip completed. clean up */
@@ -4828,6 +4827,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
4828 to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc)); 4827 to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
4829 int planes_count = 0; 4828 int planes_count = 0;
4830 unsigned long flags; 4829 unsigned long flags;
4830 u64 last_flip_vblank;
4831 bool vrr_active = acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE;
4831 4832
4832 /* update planes when needed */ 4833 /* update planes when needed */
4833 for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { 4834 for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
@@ -4859,6 +4860,16 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
4859 /* In commit tail framework this cannot happen */ 4860 /* In commit tail framework this cannot happen */
4860 WARN_ON(1); 4861 WARN_ON(1);
4861 } 4862 }
4863
4864 /* For variable refresh rate mode only:
4865 * Get vblank of last completed flip to avoid > 1 vrr flips per
4866 * video frame by use of throttling, but allow flip programming
4867 * anywhere in the possibly large variable vrr vblank interval
4868 * for fine-grained flip timing control and more opportunity to
4869 * avoid stutter on late submission of amdgpu_dm_do_flip() calls.
4870 */
4871 last_flip_vblank = acrtc_attach->last_flip_vblank;
4872
4862 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 4873 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
4863 4874
4864 if (!pflip_needed || plane->type == DRM_PLANE_TYPE_OVERLAY) { 4875 if (!pflip_needed || plane->type == DRM_PLANE_TYPE_OVERLAY) {
@@ -4882,10 +4893,18 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
4882 if (plane->type == DRM_PLANE_TYPE_PRIMARY) 4893 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
4883 drm_crtc_vblank_get(crtc); 4894 drm_crtc_vblank_get(crtc);
4884 4895
4896 /* Use old throttling in non-vrr fixed refresh rate mode
4897 * to keep flip scheduling based on target vblank counts
4898 * working in a backwards compatible way, e.g., clients
4899 * using GLX_OML_sync_control extension.
4900 */
4901 if (!vrr_active)
4902 last_flip_vblank = drm_crtc_vblank_count(crtc);
4903
4885 amdgpu_dm_do_flip( 4904 amdgpu_dm_do_flip(
4886 crtc, 4905 crtc,
4887 fb, 4906 fb,
4888 (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank, 4907 (uint32_t) last_flip_vblank + *wait_for_vblank,
4889 dc_state); 4908 dc_state);
4890 } 4909 }
4891 4910