summaryrefslogtreecommitdiffstats
path: root/video/out/vulkan
Commit message (Collapse)AuthorAgeFilesLines
* options: remove explicit initialization of integers to 0Christoph Heinrich2023-02-211-5/+1
|
* options: transition options from OPT_FLAG to OPT_BOOLChristoph Heinrich2023-02-211-4/+4
| | | | | | c78482045444c488bb7948305d583a55d17cd236 introduced a bool option type as a replacement for the flag type, but didn't actually transition and remove the flag type because it would have been too much mundane work.
* x11: remove PresentNotifyMSC from egl/glx/vulkan to fix xpresent timingSultan Alsawaf2023-01-251-3/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | PresentNotifyMSC turns out to be not only redundant, but also harmful with mesa-backed egl/glx/vulkan VOs because for all of them, mesa uses PresentPixmap behind the scenes when DRI3 is available, which already spawns a PresentCompleteNotify event when the buffer swap actually finishes. This is important because without using the timing information from these PresentCompleteKindPixmap events, there's no way for mpv to know exactly when a frame becomes visible on the display. By using PresentNotifyMSC in conjunction with DRI3-enabled mesa, two problems are created: 1. mpv assumes that a vblank won't elapse (i.e., it assumes the current MSC won't change) between the time when mesa enqueues the buffer swap and the time when mpv calls PresentNotifyMSC to ask xorg for a notification at the next MSC, relative to the current MSC at the time that xorg reads it for the PresentNotifyMSC call. This means that mpv could get a notification one or more vblanks later than it expects, since the intention here is for mpv to get a notification at the MSC that the buffer swap completes. 2. mpv assumes that a buffer swap always takes one vblank to complete, which isn't always true. A buffer swap (i.e., a page flip) could take longer than that depending on hardware conditions (if the GPU is running slowly or needs to exit a low-power state), scheduling delays (under heavy system or GPU load), or unfortunate timing (if the raster scan line happens to be at one of the last few rows of pixels and a vblank elapses just before the buffer swap is enqueued). This causes mpv to have a faulty assumption of when frames become visible. Since mpv already receives the PresentCompleteNotify events generated by mesa's buffer swaps under the hood, the PresentNotifyMSC usage is unneeded and just throws a wrench in mpv's vsync timing when xpresent is enabled. Simply removing the PresentNotifyMSC usage from the egl, glx, and vulkan VOs fixes the xpresent vsync timing.
* wayland: add wp-fractional-scale-v1 supportDudemanguy2023-01-241-0/+1
| | | | | | | | | | | | | This protocol is pretty important since it finally lets us solve the longstanding issue of fractional scaling in wayland (no more mpv doing rendering over the target resolution and then being scaled down). This protocol also can completely replace the buffer_scale usage that we are currently using for integer scaling so hopefully this can be removed sometime in the future. Note that vo_dmabuf_wayland is omitted from the fractional scale handling because we want the compositor to handle all the scaling for that VO. Fixes #9443.
* wayland: rewrite geometry and scaling handlingDudemanguy2023-01-241-2/+2
| | | | | | | | | This is in preparation for fractional scaling support. Basically, redo all the coordinates in wayland so that wl->geometry is equal exactly to what is being put out to the screen (no extra wl->scaling multiplication required). The wl->vdparams variable is also eliminated for simplicity. This changes mpv's behavior on wayland with hidpi scaling but that will be addressed in more detail with the next commit.
* wayland: make vo_wayland_reconfig a boolDudemanguy2023-01-081-4/+1
| | | | | | This was already returning true/false but the type was int. Also simplify a few places in the wayland contexts where we can just return the value of this function instead of doing redundant checks.
* vulkan: fix build error for 32bit builds with clangChristoph Reiter2023-01-081-1/+1
| | | | | | | | | | | vk->surface is a handle and not a pointer, so assign VK_NULL_HANDLE. This fixes the following build error on 32bit Windows when using clang for example, which errors out when assigning a 32bit pointer to a 64bit integer: ../mpv-0.35.0/video/out/vulkan/utils.c:37:21: error: incompatible pointer to integer conversion assigning to 'VkSurfaceKHR' (aka 'unsigned long long') from 'void *' [-Wint-conversion] vk->surface = NULL; ^ ~~~~
* vo_gpu_next: vulkan: libplacebo: unify log prefixNiklas Haas2022-10-092-4/+1
| | | | | | | | | | | | | | | | | | The new status quo is simple: all messages coming from libplacebo are marked "vo/gpu{-next}/libplacebo", regardless of the backend API (vulkan vs opengl/d3d11). Messages coming from mpv's internal vulkan code will continue to come from "vo/gpu{-next}/vulkan", and messages coming from the vo module itself will be marked "vo/gpu{-next}". This is significantly better than the old status quo of vulkan messages coming from "vo/gpu{-next}/vulkan/libplacebo" whereas opengl/d3d11 messages simply came from "vo/gpu{-next}", even when those messages originated from libplacebo. (It's worth noting that the the destructor for the log is redundant because it's attached to the ctx which is freed on uninit anyway)
* wayland: correctly handle non-CLOCK_MONOTONIC clocksDudemanguy2022-10-061-2/+2
| | | | | | | | | | | | | The wayland presentation time code currently always assumes that only CLOCK_MONOTONIC can be used. There is a naive attempt to ignore clocks other than CLOCK_MONOTONIC, but the logic is actually totally wrong and the timestamps would be used anyway. Fix this by checking a use_present bool (similar to use_present in xorg) which is set to true if we receive a valid clock in the clockid event. Additionally, allow CLOCK_MONOTONIC_RAW as a valid clockid. In practice, it should be the same as CLOCK_MONOTONIC for us (ntp/adjustime difference wouldn't matter). Since this is a linux-specific clock, add a define for it if it is not found.
* vulkan: remove --vulkan-disable-eventsNiklas Haas2022-10-051-3/+1
| | | | | | This has had no effect since libplacebo v4.192.0, and was deprecated upstream a year ago. No deprecation period in mpv is justified by this being a debug / work-around option.
* x11: avoid XPresent API calls when it's not neededDudemanguy2022-06-221-3/+6
| | | | | | | | | | | This commit kind of mixes several related things together. The main thing is to avoid calling any XPresent functions or internal functions related to presentation when the feature is not auto-whitelisted or enabled by the user. Internally rework this so it all works off of a use_present bool (have_present is eliminated because having a non-zero present_code covers exactly the same thing) and make sure it updates on runtime. Finally, put some actual logging in here whenever XPresent is enabled/disabled. Fixes #10326.
* x11: support xorg present extensionDudemanguy2022-06-191-0/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This builds off of present_sync which was introduced in a previous commit to support xorg's present extension in all of the X11 backends (sans vdpau) in mpv. It turns out there is an Xpresent library that integrates the xorg present extention with Xlib (which barely anyone seems to use), so this can be added without too much trouble. The workflow is to first setup the event by telling Xorg we would like to receive PresentCompleteNotify (there are others in the extension but this is the only one we really care about). After that, just call XPresentNotifyMSC after every buffer swap with a target_msc of 0. Xorg then returns the last presentation through its usual event loop and we go ahead and use that information to update mpv's values for vsync timing purposes. One theoretical weakness of this approach is that the present event is put on the same queue as the rest of the XEvents. It would be nicer for it be placed somewhere else so we could just wait on that queue without having to deal with other possible events in there. In theory, xcb could do that with special events, but it doesn't really matter in practice. Unsurprisingly, this doesn't work on NVIDIA. Well NVIDIA does actually receive presentation events, but for whatever the calculations used make timings worse which defeats the purpose. This works perfectly fine on Mesa however. Utilizing the previous commit that detects Xrandr providers, we can enable this mechanism for users that have both Mesa and not NVIDIA (to avoid messing up anyone that has a switchable graphics system or such). Patches welcome if anyone figures out how to fix this on NVIDIA. Unlike the EGL/GLX sync extensions, the present extension works with any graphics API (good for vulkan since its timing extension has been in development hell). NVIDIA also happens to have zero support for the EGL/GLX sync extensions, so we can just remove it with no loss. Only Xorg ever used it and other backends already have their own present methods. vo_vdpau VO is a special case that has its own fancying timing code in its flip_page. This presumably works well, and I have no way of testing it so just leave it as it is.
* vo: move wayland presentation to separate filesDudemanguy2022-06-191-6/+4
| | | | | | | | | | | | | | | | | | | | | | | | | Wayland had some specific code that it used for implementing the presentation time protocol. It turns out that xorg's present extension is extremely similar, so it would be silly to duplicate this whole mess again. Factor this out to separate, independent code and introduce the mp_present struct which is used for handling the ust/msc values and some other associated values. Also, add in some helper functions so all the dirty details live specifically in present_sync. The only wayland-specific part is actually obtaining ust/msc values. Since only wayland or xorg are expected to use this, add a conditional to the build that only adds this file when either one of those are present. You may observe that sbc is completely omitted. This field existed in wayland, but was completely unused (presentation time doesn't return this). Xorg's present extension also doesn't use this so just get rid of it all together. The actual calculation is slightly altered so it is correct for our purposes. We want to get the presentation event of the last frame that was just occured (this function executes right after the buffer swap). The adjustment is to just remove the vsync_duration subtraction. Also, The overly-complicated queue approach is removed. This has no actual use in practice (on wayland or xorg). Presentation statistics are only ever used after the immediate preceding swap to update vsync timings or thrown away.
* x11: avoid wasteful rendering when possibleDudemanguy2022-04-111-1/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Because wayland is a special snowflake, mpv wound up incorporating a lot of logic into its render loop where visibilty checks are performed before rendering anything (in the name of efficiency of course). Only wayland actually uses this, but there's no reason why other backends (x11 in this commit) can't be smarter. It's far easier on xorg since we can just query _NET_WM_STATE_HIDDEN directly and not have to do silly callback dances. The function, vo_x11_check_net_wm_state_change, already tracks net wm changes, including _NET_WM_STATE_HIDDEN. There is an already existing window_hidden variable but that is actually just for checking if the window was mapped and has nothing to do with this particular atom. mpv also currently assumes that a _NET_WM_STATE_HIDDEN is exactly the same as being minimized but according to the spec, that's not neccesarily true (in practice, it's likely that these are the same though). Anyways, just keep track of this state in a new variable (hidden) and use that for determing if mpv should render or not. There is one catch though: this cannot work if a display sync mode is used. This is why the previous commit is needed. The display sync modes in mpv require a blocking vsync implementation since its render loop is directly driven by vsync. In xorg, if nothing is actually rendered, then there's nothing for eglSwapBuffers (or FIFO for vulkan) to block on so it returns immediately. This, of course, results in completely broken video. We just need to check to make sure that we aren't in a display sync mode before trying to be smart about rendering. Display sync is power inefficient anyways, so no one is really being hurt here. As an aside, this happens to work in wayland because there's basically a custom (and ugly) vsync blocking function + timeout but that's off topic.
* wayland: unify visibility checking codeDudemanguy2022-04-111-5/+1
| | | | | | | | | | | A bit of a personal pet peeve. vulkan, opengl, and wlshm all had different methods for doing wayland's "check for visibility before drawing" thing. The specific backend doesn't matter in this case and the logic should all be shared. Additionally, the external swapchain that the opengl code on wayland uses is done away with and it instead copies vulkan by using a param. This keeps things looking more uniform across backends and also makes it easier to extend to other platforms (see the next couple of commits).
* vulkan: correctly inherit proc_addr pointerNiklas Haas2022-03-131-0/+1
| | | | | | As found out by @philipl, failing to pass this from the VkInstance to the VkDevice is bad style. We might want to override the get_proc_addr pointer in the future.
* libplacebo: switch to v4 naming conventionNiklas Haas2022-02-031-4/+4
| | | | | All of these const struct pointers got typedefs, clean up the code accordingly.
* libplacebo: update log helpersNiklas Haas2022-02-034-17/+13
| | | | | Use the pl_log APIs introduced in libplacebo v4, replacing the deprecated pl_context concept.
* vo_gpu: libplacebo: make version logging slightly clearerNiklas Haas2021-11-191-1/+2
| | | | Matches what `pl_log_create` does as well.
* vo_gpu: vulkan: open DRM render fd when using VK_KHR_displayPhilip Langdale2021-11-151-2/+102
| | | | | | | | | | | | | | | While the basic Vulkan Display context can theoretically drive the display without the involvement of any non-Vulkan code, that prevents us from using VAAPI acceleration. When initialising VAAPI without a window system, we need to provide it with an opened DRM render fd corresponding to the device to use. In the context of using VK_KHR_display, that means we need to identify which DRM device matches the selected Vulkan device, and then open its render fd and set the necessary state that VAAPI expects to find. With that done, the normal VAAPI<->Vulkan interop can kick in and we get working acceleration
* vo_gpu_next: call start_frame in vulkan/context.cDudemanguy2021-11-041-2/+6
| | | | | | | | | In practice, this is for wayland. vo_gpu_next doesn't check the check_visible parameter since it didn't descend into the vulkan/context.c file when starting a frame. To make this happen, just call the start_frame function pointer but pass NULL as the ra_fbo. In there, we can do the visibility checks and after that bail out of the start_frame function if ra_fbo is NULL.
* wayland_vk: rename start_frame to check_visibleDudemanguy2021-11-043-9/+10
| | | | | | | | | | This vulkan-specific parameter was poorly named and probably causes confusion. Just rename it to check_visible instead to make clear what is going on here. Only wayland uses it for now but in theory anyone else can. As an aside, wayland egl accomplishes this by using an external swapchain instead (an opengl-only concept in the mpv code). This may or may not need to be changed in the future when gpu-next gets opengl support.
* vo_gpu: vulkan: expose swapchain to mpvk_ctxNiklas Haas2021-11-032-8/+8
| | | | So I can reuse it in vo_gpu_next.
* vo_gpu: libplacebo: drop conditional code paths for old versionsNiklas Haas2021-10-041-4/+0
| | | | No longer needed with the bump to v3.104.
* wayland: fix wl_surface_set_buffer_scale usageDudemanguy2021-06-271-1/+0
| | | | | | | | | | | The wl_surface lives for the entire lifetime of the vo. It's only neccesary to set the scale initially and when the output scaling changes (the surface moves to a different output with a different scale or the output itself changes it scale). All of the calls that were being made in the egl/vulkan resize functions are not needed. vo_wlshm wasn't correctly rescaling itself before this commit since it had no logic to handle scale changes. This should all be shared, common code in the surface/output listeners.
* wayland: always be sure to initially try to renderDudemanguy2021-06-271-1/+1
| | | | | | | | | | | | | | | | | | | A subtle regression from c26d833. On sway if mpv was set to be a floating window in the config, set_buffer_scale would actually get applied twice according to the wayland log. That meant a 1920x1080 window would appear as a 960x540 window if the scale of the wl_output was set to 2. This only affected egl on sway (didn't occur on weston and was too lazy to try anything else; probably they were fine). Since wl->render is initially false, that meant that the very first run through the render loop returns false. This probably caused something weird to happen with the set_buffer_scale calls (the egl window gets created and everything but mpv doesn't write to it just yet) which makes the set_buffer_scale call happen an extra time. Since it was always intended for mpv to initally render, this is worth fixing. Just chnage wl->render to wl->hidden (again) and flip the bools around. That way, the initial false value results in render == true and mpv tries to draw on the first pass. This fixes the weird scaling behavior because reasons.
* wayland: remove unused includesDudemanguy2021-06-271-3/+0
| | | | Presentation time only lives in in wayland_common.
* wayland: reorganize wayland common codeDudemanguy2021-06-261-1/+1
| | | | | | | Mostly a cosmetic change that (hopefully) makes things look better. Some functions and structs that were previously being exported in the wayland header were made static to the wayland_common.c file (these shouldn't be accessed by anyone else).
* vo_gpu: vulkan: displayvk: Fix handling of unconnected planesPhilip Langdale2021-06-121-1/+6
| | | | | | | | If a plane is not connected to any displays, we won't set an entry in the mapping of planes to displays. So ensure these unset entries are null and skip them. Fixes #8913
* vo_gpu: vulkan: implement a VkDisplayKHR backed contextPhilip Langdale2021-06-111-0/+390
| | | | | | | | | | | | | | | | | | | | | | | | This is the Vulkan equivalent of the drm context for OpenGL, with the big difference that it's implemented purely in terms of Vulkan calls and doesn't actually require drm or kms. The basic idea is to identify a display, mode, and plane on a device, and then create a display backed surface for the swapchain. In theory, past that point, everything is the same, and this is in fact the case on Intel hardware. I can get a video playing on a vt. On nvidia, naturally, things don't work that way. Instead, nvidia only implemented the extension for scenarios where a VR application is stealing a display from a running window system, and not for standalone scenarios. With additional code, I've got this scenario to work but that's a separate incremental change. Other people have tested on AMD, and report roughly the same behaviour as on Intel. Note, that in this change, the VT will not be correctly restored after qutting. The only way to restore the VT is to introduce some drm specific code which I will illustrate in a separate change.
* vo_gpu: vulkan: provide a helper to access device name optionPhilip Langdale2021-06-112-0/+17
| | | | | | | | | | | The VkDisplayKHR context type requires making calls against the physical device before the libplacebo context is initialised. That means we can't simply use the physical device object that libplacebo would create - instead we have to create a separate one, but make sure it's referring to the same physical device. To that end, we need the device name that the user may have requested so we can pass it on.
* wayland: shuffle around the render loop againDudemanguy2021-05-241-5/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Take two. f4e89dd went wrong by moving vo_wayland_wait_frame before start_frame was called. Whether or not this matters depends on the compositor, but some weird things can happen. Basically, it's a scheduling issue. vo_wayland_wait_frame queues all events and sends them to the server to process (with no blocking if presentation time is available). If mpv changes state while rendering (and this function is called before every frame is drawn), then that event also gets dispatched and sent to the compositor. This, in some cases, can cause some funny behavior because the next frame gets attached to the surface while the old buffer is getting released. It's safer to call this function after the swap already happens and well before mpv calls its next draw. There's no weird scheduling of events, and the compositor log is more normal. The second part of this is to fix some stuttering issues. This is mostly just conjecture, but probably what was happening was this thing called "composition". The easiest way to see this is to play a video on the default audio sync mode (probably easiest to see on a typical 23.976 video). Have that in a window and float it over firefox (floating windows are bloat on a tiling wm anyway). Then in firefox, do some short bursts of smooth scrolling (likely uses egl). Some stutter in video rendering could be observed, particularly in panning shots. Compositors are supposed to prevent tearing so what likely was happening was that the compositor was simply holding the buffer a wee bit longer to make sure it happened in sync with the smooth scrolling. Because the mpv code waits precisely on presentation time, the loop would timeout on occasion instead of receiving the frame callback. This would then lead to a skipped frame when rendering and thus causing stuttering. The fix is simple: just only count consecutive timeouts as not receiving frame callback. If a compositor holds the mpv buffer slightly longer to avoid tearing, then we will definitely receive frame callback on the next round of the render loop. This logic also appears to be sound for plasma (funfact: Plasma always returns frame callback even when the window is hidden. Not sure what's up with that, but luckily it doesn't matter to us.), so get rid of the goofy 1/vblank_time thing and just keep it a simple > 1 check.
* wayland: simplify render loopDudemanguy2021-05-221-11/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is actually a very nice simplification that should have been thought of years ago (sue me). In a nutshell, the story with the wayland code is that the frame callback and swap buffer behavior doesn't fit very well with mpv's rendering loop. It's been refactored/changed quite a few times over the years and works well enough but things could be better. The current iteration works with an external swapchain to check if we have frame callback before deciding whether or not to render. This logic was implemented in both egl and vulkan. This does have its warts however. There's some hidden state detection logic which works but is kind of ugly. Since wayland doesn't allow clients to know if they are actually visible (questionable but whatever), you can just reasonably assume that if a bunch of callbacks are missed in a row, you're probably not visible. That's fine, but it is indeed less than ideal since the threshold is basically entirely arbitrary and mpv does do a few wasteful renders before it decides that the window is actually hidden. The biggest urk in the vo_wayland_wait_frame is the use of wl_display_roundtrip. Wayland developers would probably be offended by the way mpv abuses that function, but essentially it was a way to have semi-blocking behavior needed for display-resample to work. Since the swap interval must be 0 on wayland (otherwise it will block the entire player's rendering loop), we need some other way to wait on vsync. The idea here was to dispatch and poll a bunch of wayland events, wait (with a timeout) until we get frame callback, and then wait for the compositor to process it. That pretty much perfectly waits on vsync and lets us keep all the good timings and all that jazz that we want for mpv. The problem is that wl_display_roundtrip is conceptually a bad function. It can internally call wl_display_dispatch which in certain instances, empty event queue, will block forever. Now strictly speaking, this probably will never, ever happen (once I was able to to trigger it by hardcoding an error into a compositor), but ideally vo_wayland_wait_frame should never infinitely block and stall the player. Unfortunately, removing that function always lead to problems with timings and unsteady vsync intervals so it survived many refactors. Until now, of course. In wayland, the ideal is to never do wasteful rendering (i.e. don't render if the window isn't visible). Instead of wrestling around with hidden states and possible missed vblanks, let's rearrange the wayland rendering logic so we only ever draw a frame when the frame callback is returned to use (within a reasonable timeout to avoid blocking forever). This slight rearrangement of the wait allows for several simplifications to be made. Namely, wl_display_roundtrip stops being needed. Instead, we can rely entirely on totally nonblocking calls (dispatch_pending, flush, and so on). We still need to poll the fd here to actually get the frame callback event from the compositor, but there's no longer any reason to do extra waiting. As soon as we get the callback, we immediately draw. This works quite well and has stable vsync (display-resample and audio). Additionally, all of the logic about hidden states is no longer needed. If vo_wayland_wait_frame times out, it's okay to assume immediately that the window is not visible and skip rendering. Unfortunately, there's one limitation on this new approach. It will only work correctly if the compositor implements presentation time. That means a reduced version of the old way still has to be carried around in vo_wayland_wait_frame. So if the compositor has no presentation time, then we are forced to use wl_display_roundtrip and juggle some funny assumptions about whether or not the window is hidden or not. Plasma is the only real notable compositor without presentation time at this stage so perhaps this "legacy" mechanism could be removed in the future.
* options: Make validation and help possible for all option typesPhilip Langdale2021-03-281-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
* wayland: unify frame/presentation callback codeDudemanguy2020-12-141-76/+0
| | | | | | | | | | | | | | | | Originally when presentation time was implemented, the frame callback and presentation feedback functions were called in each rendering api's separate backend (egl and vulkan). This meant that their respective structs were basically copy and pasted across both files. Plus later vo_wlshm started using frame callbacks too. Things got refactored a few times and it turns out there's actually no need to have these things separate anymore. The frame callback can just be initialized in vo_wayland_init and then everything else will follow from there. Just move all of this code to wayland_common and get rid of the duplication. S