From 5540b9440a33c42461978c43cf396f56c1e0291a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 14 Aug 2025 05:16:12 +0000 Subject: [PATCH] CLI: move VSync from an environment variable to an argument Add a command line argument --gpu-vsync on/off/auto. Prefer command line arguments for GPU settings, as it means the value is error checked and set when Blender starts. Also refactor GHOST_Context to take a parameter argument which includes the stereo-visual & debug arguments and includes the newly added vsync setting. This makes it possible to add GPU context parameters more easily in the future. It also removes redundant parsing & setting the VSync setting for off-screen contexts. Changes to recent PR !143049. Ref !144473 --- intern/ghost/GHOST_Types.h | 56 +++++++++++++++++++ intern/ghost/intern/GHOST_Context.cc | 6 -- intern/ghost/intern/GHOST_Context.hh | 18 +++--- intern/ghost/intern/GHOST_ContextD3D.cc | 4 +- intern/ghost/intern/GHOST_ContextD3D.hh | 2 +- intern/ghost/intern/GHOST_ContextEGL.cc | 15 +++-- intern/ghost/intern/GHOST_ContextEGL.hh | 2 +- intern/ghost/intern/GHOST_ContextGLX.cc | 16 +++--- intern/ghost/intern/GHOST_ContextGLX.hh | 2 +- intern/ghost/intern/GHOST_ContextMTL.hh | 5 +- intern/ghost/intern/GHOST_ContextMTL.mm | 21 ++++--- intern/ghost/intern/GHOST_ContextNone.hh | 2 +- intern/ghost/intern/GHOST_ContextSDL.cc | 15 ++--- intern/ghost/intern/GHOST_ContextSDL.hh | 2 +- intern/ghost/intern/GHOST_ContextVK.cc | 21 +++---- intern/ghost/intern/GHOST_ContextVK.hh | 4 +- intern/ghost/intern/GHOST_ContextWGL.cc | 17 +++--- intern/ghost/intern/GHOST_ContextWGL.hh | 2 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 11 ++-- intern/ghost/intern/GHOST_SystemHeadless.hh | 16 +++--- intern/ghost/intern/GHOST_SystemSDL.cc | 9 ++- intern/ghost/intern/GHOST_SystemWayland.cc | 40 ++++++------- intern/ghost/intern/GHOST_SystemWin32.cc | 40 ++++++------- intern/ghost/intern/GHOST_SystemX11.cc | 16 +++--- intern/ghost/intern/GHOST_Window.cc | 10 ++-- intern/ghost/intern/GHOST_Window.hh | 6 +- intern/ghost/intern/GHOST_WindowCocoa.hh | 6 +- intern/ghost/intern/GHOST_WindowCocoa.mm | 10 ++-- intern/ghost/intern/GHOST_WindowNULL.hh | 4 +- intern/ghost/intern/GHOST_WindowSDL.cc | 7 ++- intern/ghost/intern/GHOST_WindowSDL.hh | 4 +- intern/ghost/intern/GHOST_WindowWayland.cc | 15 ++--- intern/ghost/intern/GHOST_WindowWayland.hh | 4 +- intern/ghost/intern/GHOST_WindowWin32.cc | 16 +++--- intern/ghost/intern/GHOST_WindowWin32.hh | 4 +- intern/ghost/intern/GHOST_WindowX11.cc | 18 +++--- intern/ghost/intern/GHOST_WindowX11.hh | 6 +- source/blender/gpu/GPU_context.hh | 12 ++++ source/blender/gpu/intern/gpu_context.cc | 16 ++++++ .../windowmanager/intern/wm_playanim.cc | 4 ++ .../blender/windowmanager/intern/wm_window.cc | 8 +++ source/creator/creator_args.cc | 43 +++++++++++++- 42 files changed, 330 insertions(+), 205 deletions(-) diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index c639d715585..67915bd5651 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -115,6 +115,8 @@ typedef struct GHOST_CursorGenerator { typedef enum { GHOST_gpuStereoVisual = (1 << 0), GHOST_gpuDebugContext = (1 << 1), + GHOST_gpuVSyncIsOverridden = (1 << 2), + } GHOST_GPUFlags; typedef enum GHOST_DialogOptions { @@ -790,8 +792,62 @@ typedef struct { uint device_id; } GHOST_GPUDevice; +/** + * Options for VSync. + * + * \note with the exception of #GHOST_kVSyncModeUnset, + * these map to the OpenGL "swap interval" argument. + */ +typedef enum { + /** Up to the GPU driver to choose. */ + GHOST_kVSyncModeUnset = -2, + /** Adaptive sync (OpenGL only). */ + GHOST_kVSyncModeAuto = -1, + /** Disable, useful for unclasped redraws for testing performance. */ + GHOST_kVSyncModeOff = 0, + /** Force enable. */ + GHOST_kVSyncModeOn = 1, +} GHOST_TVSyncModes; + +/** + * Settings used to create a GPU context. + * + * \note Avoid adding values here unless they apply across multiple context implementations. + * Otherwise the settings would be better added as extra arguments, only passed to that class. + */ +typedef struct { + bool is_stereo_visual; + bool is_debug; + GHOST_TVSyncModes vsync; +} GHOST_ContextParams; + +#define GHOST_CONTEXT_PARAMS_NONE \ + { \ + /*is_stereo_visual*/ false, /*is_debug*/ false, /*vsync*/ GHOST_kVSyncModeUnset, \ + } + +#define GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpuSettings) \ + { \ + /*is_stereo_visual*/ false, \ + /*is_debug*/ (((gpuSettings).flags & GHOST_gpuDebugContext) != 0), \ + /*vsync*/ GHOST_kVSyncModeUnset, \ + } + +#define GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpuSettings) \ + { \ + /*is_stereo_visual*/ (((gpuSettings).flags & GHOST_gpuStereoVisual) != 0), \ + /*is_debug*/ (((gpuSettings).flags & GHOST_gpuDebugContext) != 0), /*vsync*/ \ + (((gpuSettings).flags & GHOST_gpuVSyncIsOverridden) ? (gpuSettings).vsync : \ + GHOST_kVSyncModeUnset), \ + } + typedef struct { int flags; + /** + * Use when `flags & GHOST_gpuVSyncIsOverridden` is set. + * See #GHOST_ContextParams::vsync. + */ + GHOST_TVSyncModes vsync; GHOST_TDrawingContextType context_type; GHOST_GPUDevice preferred_device; } GHOST_GPUSettings; diff --git a/intern/ghost/intern/GHOST_Context.cc b/intern/ghost/intern/GHOST_Context.cc index 0d0dff78a00..d225220fa3e 100644 --- a/intern/ghost/intern/GHOST_Context.cc +++ b/intern/ghost/intern/GHOST_Context.cc @@ -142,9 +142,3 @@ void GHOST_Context::initClearGL() glClearColor(0.000, 0.000, 0.000, 0.000); } #endif - -const char *GHOST_Context::getEnvVarVSyncString() -{ - const char *ghost_vsync_string = getenv("BLENDER_VSYNC"); - return ghost_vsync_string; -} diff --git a/intern/ghost/intern/GHOST_Context.hh b/intern/ghost/intern/GHOST_Context.hh index 27c7d01d921..f81eb7e7baa 100644 --- a/intern/ghost/intern/GHOST_Context.hh +++ b/intern/ghost/intern/GHOST_Context.hh @@ -13,6 +13,7 @@ #include "GHOST_Types.h" #include // for nullptr +#include class GHOST_Context : public GHOST_IContext { protected: @@ -21,9 +22,9 @@ class GHOST_Context : public GHOST_IContext { public: /** * Constructor. - * \param stereoVisual: Stereo visual for quad buffered stereo. + * \param context_params: Parameters to use when initializing the context. */ - GHOST_Context(bool stereoVisual) : m_stereoVisual(stereoVisual) {} + GHOST_Context(const GHOST_ContextParams &context_params) : m_context_params(context_params) {} /** * Destructor. @@ -117,7 +118,13 @@ class GHOST_Context : public GHOST_IContext { */ bool isStereoVisual() const { - return m_stereoVisual; + return m_context_params.is_stereo_visual; + } + + /** Get the VSync value. */ + virtual GHOST_TVSyncModes getVSync() + { + return m_context_params.vsync; } /** @@ -160,7 +167,7 @@ class GHOST_Context : public GHOST_IContext { #endif protected: - bool m_stereoVisual; + GHOST_ContextParams m_context_params; /** Caller specified, not for internal use. */ void *m_user_data = nullptr; @@ -169,9 +176,6 @@ class GHOST_Context : public GHOST_IContext { static void initClearGL(); #endif - /** For performance measurements with VSync disabled. */ - static const char *getEnvVarVSyncString(); - MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_Context") }; diff --git a/intern/ghost/intern/GHOST_ContextD3D.cc b/intern/ghost/intern/GHOST_ContextD3D.cc index cc4a5577a57..211254f012a 100644 --- a/intern/ghost/intern/GHOST_ContextD3D.cc +++ b/intern/ghost/intern/GHOST_ContextD3D.cc @@ -20,8 +20,8 @@ HMODULE GHOST_ContextD3D::s_d3d_lib = nullptr; PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = nullptr; -GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd) - : GHOST_Context(stereoVisual), m_hWnd(hWnd) +GHOST_ContextD3D::GHOST_ContextD3D(const GHOST_ContextParams &context_params, HWND hWnd) + : GHOST_Context(context_params), m_hWnd(hWnd) { } diff --git a/intern/ghost/intern/GHOST_ContextD3D.hh b/intern/ghost/intern/GHOST_ContextD3D.hh index c09afcc6b1b..990774e11cc 100644 --- a/intern/ghost/intern/GHOST_ContextD3D.hh +++ b/intern/ghost/intern/GHOST_ContextD3D.hh @@ -23,7 +23,7 @@ class GHOST_ContextD3D : public GHOST_Context { friend class GHOST_XrGraphicsBindingVulkanD3D; public: - GHOST_ContextD3D(bool stereoVisual, HWND hWnd); + GHOST_ContextD3D(const GHOST_ContextParams &context_params, HWND hWnd); ~GHOST_ContextD3D() override; /** diff --git a/intern/ghost/intern/GHOST_ContextEGL.cc b/intern/ghost/intern/GHOST_ContextEGL.cc index 3fe150fecd2..49b5a6a643d 100644 --- a/intern/ghost/intern/GHOST_ContextEGL.cc +++ b/intern/ghost/intern/GHOST_ContextEGL.cc @@ -187,7 +187,7 @@ template T &choose_api(EGLenum api, T &a, T &b, T &c) } GHOST_ContextEGL::GHOST_ContextEGL(const GHOST_System *const system, - bool stereoVisual, + const GHOST_ContextParams &context_params, EGLNativeWindowType nativeWindow, EGLNativeDisplayType nativeDisplay, EGLint contextProfileMask, @@ -196,7 +196,7 @@ GHOST_ContextEGL::GHOST_ContextEGL(const GHOST_System *const system, EGLint contextFlags, EGLint contextResetNotificationStrategy, EGLenum api) - : GHOST_Context(stereoVisual), + : GHOST_Context(context_params), m_system(system), m_nativeDisplay(nativeDisplay), m_nativeWindow(nativeWindow), @@ -336,10 +336,10 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext() std::vector attrib_list; EGLint num_config = 0; - if (m_stereoVisual) { + if (m_context_params.is_stereo_visual) { fprintf(stderr, "Warning! Stereo OpenGL ES contexts are not supported.\n"); } - m_stereoVisual = false; /* It doesn't matter what the Window wants. */ + m_context_params.is_stereo_visual = false; /* It doesn't matter what the Window wants. */ EGLDisplay prev_display = eglGetCurrentDisplay(); EGLSurface prev_draw = eglGetCurrentSurface(EGL_DRAW); @@ -626,10 +626,9 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext() } { - const char *ghost_vsync_string = getEnvVarVSyncString(); - if (ghost_vsync_string) { - int swapInterval = atoi(ghost_vsync_string); - setSwapInterval(swapInterval); + const GHOST_TVSyncModes vsync = getVSync(); + if (vsync != GHOST_kVSyncModeUnset) { + setSwapInterval(int(vsync)); } } diff --git a/intern/ghost/intern/GHOST_ContextEGL.hh b/intern/ghost/intern/GHOST_ContextEGL.hh index f43d37074dc..ea9338fc9e3 100644 --- a/intern/ghost/intern/GHOST_ContextEGL.hh +++ b/intern/ghost/intern/GHOST_ContextEGL.hh @@ -35,7 +35,7 @@ class GHOST_ContextEGL : public GHOST_Context { * Constructor. */ GHOST_ContextEGL(const GHOST_System *const system, - bool stereoVisual, + const GHOST_ContextParams &context_params, EGLNativeWindowType nativeWindow, EGLNativeDisplayType nativeDisplay, EGLint contextProfileMask, diff --git a/intern/ghost/intern/GHOST_ContextGLX.cc b/intern/ghost/intern/GHOST_ContextGLX.cc index 8dd13655298..fe9ad5dbe28 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.cc +++ b/intern/ghost/intern/GHOST_ContextGLX.cc @@ -28,7 +28,7 @@ static GLboolean _glewSearchExtension(const char *name, const GLubyte *start, co GLXContext GHOST_ContextGLX::s_sharedContext = None; int GHOST_ContextGLX::s_sharedCount = 0; -GHOST_ContextGLX::GHOST_ContextGLX(bool stereoVisual, +GHOST_ContextGLX::GHOST_ContextGLX(const GHOST_ContextParams &context_params, Window window, Display *display, GLXFBConfig fbconfig, @@ -37,7 +37,7 @@ GHOST_ContextGLX::GHOST_ContextGLX(bool stereoVisual, int contextMinorVersion, int contextFlags, int contextResetNotificationStrategy) - : GHOST_Context(stereoVisual), + : GHOST_Context(context_params), m_display(display), m_fbconfig(fbconfig), m_window(window), @@ -244,7 +244,8 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() int glx_attribs[64]; int fbcount = 0; - GHOST_X11_GL_GetAttributes(glx_attribs, 64, m_stereoVisual, false, true); + GHOST_X11_GL_GetAttributes( + glx_attribs, 64, m_context_params.is_stereo_visual, false, true); framebuffer_config = glXChooseFBConfig( m_display, DefaultScreen(m_display), glx_attribs, &fbcount); @@ -281,10 +282,11 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() glXMakeCurrent(m_display, m_window, m_context); /* For performance measurements with VSync disabled. */ - const char *ghost_vsync_string = getEnvVarVSyncString(); - if (ghost_vsync_string) { - int swapInterval = atoi(ghost_vsync_string); - setSwapInterval(swapInterval); + { + const GHOST_TVSyncModes vsync = getVSync(); + if (vsync != GHOST_kVSyncModeUnset) { + setSwapInterval(int(vsync)); + } } if (m_window) { diff --git a/intern/ghost/intern/GHOST_ContextGLX.hh b/intern/ghost/intern/GHOST_ContextGLX.hh index 4ab1b8c3acc..0db3b947b53 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.hh +++ b/intern/ghost/intern/GHOST_ContextGLX.hh @@ -29,7 +29,7 @@ class GHOST_ContextGLX : public GHOST_Context { /** * Constructor. */ - GHOST_ContextGLX(bool stereoVisual, + GHOST_ContextGLX(const GHOST_ContextParams &context_params, Window window, Display *display, GLXFBConfig fbconfig, diff --git a/intern/ghost/intern/GHOST_ContextMTL.hh b/intern/ghost/intern/GHOST_ContextMTL.hh index d0d80cda458..e047ec53431 100644 --- a/intern/ghost/intern/GHOST_ContextMTL.hh +++ b/intern/ghost/intern/GHOST_ContextMTL.hh @@ -41,7 +41,9 @@ class GHOST_ContextMTL : public GHOST_Context { /** * Constructor. */ - GHOST_ContextMTL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, int debug); + GHOST_ContextMTL(const GHOST_ContextParams &context_params, + NSView *metalView, + CAMetalLayer *metalLayer); /** * Destructor. @@ -157,7 +159,6 @@ class GHOST_ContextMTL : public GHOST_Context { id); int mtl_SwapInterval; - const bool m_debug; static int s_sharedCount; diff --git a/intern/ghost/intern/GHOST_ContextMTL.mm b/intern/ghost/intern/GHOST_ContextMTL.mm index 8dd20f87a57..89154f852db 100644 --- a/intern/ghost/intern/GHOST_ContextMTL.mm +++ b/intern/ghost/intern/GHOST_ContextMTL.mm @@ -46,15 +46,13 @@ static void ghost_fatal_error_dialog(const char *msg) MTLCommandQueue *GHOST_ContextMTL::s_sharedMetalCommandQueue = nil; int GHOST_ContextMTL::s_sharedCount = 0; -GHOST_ContextMTL::GHOST_ContextMTL(bool stereoVisual, +GHOST_ContextMTL::GHOST_ContextMTL(const GHOST_ContextParams &context_params, NSView *metalView, - CAMetalLayer *metalLayer, - int debug) - : GHOST_Context(stereoVisual), + CAMetalLayer *metalLayer) + : GHOST_Context(context_params), m_metalView(metalView), m_metalLayer(metalLayer), - m_metalRenderPipeline(nil), - m_debug(debug) + m_metalRenderPipeline(nil) { @autoreleasepool { /* Initialize Metal Swap-chain. */ @@ -72,7 +70,7 @@ GHOST_ContextMTL::GHOST_ContextMTL(bool stereoVisual, /* Prepare offscreen GHOST Context Metal device. */ id metalDevice = MTLCreateSystemDefaultDevice(); - if (m_debug) { + if (m_context_params.is_debug) { printf("Selected Metal Device: %s\n", [metalDevice.name UTF8String]); } @@ -88,10 +86,11 @@ GHOST_ContextMTL::GHOST_ContextMTL(bool stereoVisual, m_metalLayer.device = metalDevice; m_metalLayer.allowsNextDrawableTimeout = NO; - const char *ghost_vsync_string = getEnvVarVSyncString(); - if (ghost_vsync_string) { - int swapInterval = atoi(ghost_vsync_string); - m_metalLayer.displaySyncEnabled = swapInterval != 0 ? YES : NO; + { + const GHOST_TVSyncModes vsync = getVSync(); + if (vsync != GHOST_kVSyncModeUnset) { + m_metalLayer.displaySyncEnabled = (vsync == GHOST_kVSyncModeOff) ? NO : YES; + } } /* Enable EDR support. This is done by: diff --git a/intern/ghost/intern/GHOST_ContextNone.hh b/intern/ghost/intern/GHOST_ContextNone.hh index 11eccd85cd8..ccd2e56dc2f 100644 --- a/intern/ghost/intern/GHOST_ContextNone.hh +++ b/intern/ghost/intern/GHOST_ContextNone.hh @@ -14,7 +14,7 @@ class GHOST_ContextNone : public GHOST_Context { public: - GHOST_ContextNone(bool stereoVisual) : GHOST_Context(stereoVisual) {} + GHOST_ContextNone(const GHOST_ContextParams &context_params) : GHOST_Context(context_params) {} /** * Dummy function diff --git a/intern/ghost/intern/GHOST_ContextSDL.cc b/intern/ghost/intern/GHOST_ContextSDL.cc index 26455ff72ca..1763018b02b 100644 --- a/intern/ghost/intern/GHOST_ContextSDL.cc +++ b/intern/ghost/intern/GHOST_ContextSDL.cc @@ -16,14 +16,14 @@ SDL_GLContext GHOST_ContextSDL::s_sharedContext = nullptr; int GHOST_ContextSDL::s_sharedCount = 0; -GHOST_ContextSDL::GHOST_ContextSDL(bool stereoVisual, +GHOST_ContextSDL::GHOST_ContextSDL(const GHOST_ContextParams &context_params, SDL_Window *window, int contextProfileMask, int contextMajorVersion, int contextMinorVersion, int contextFlags, int contextResetNotificationStrategy) - : GHOST_Context(stereoVisual), + : GHOST_Context(context_params), m_window(window), m_hidden_window(nullptr), m_contextProfileMask(contextProfileMask), @@ -106,7 +106,7 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext() SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); } - if (m_stereoVisual) { + if (m_context_params.is_stereo_visual) { SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } @@ -134,10 +134,11 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext() success = (SDL_GL_MakeCurrent(m_window, m_context) < 0) ? GHOST_kFailure : GHOST_kSuccess; - const char *ghost_vsync_string = getEnvVarVSyncString(); - if (ghost_vsync_string) { - int swapInterval = atoi(ghost_vsync_string); - setSwapInterval(swapInterval); + { + const GHOST_TVSyncModes vsync = getVSync(); + if (vsync != GHOST_kVSyncModeUnset) { + setSwapInterval(int(vsync)); + } } initClearGL(); diff --git a/intern/ghost/intern/GHOST_ContextSDL.hh b/intern/ghost/intern/GHOST_ContextSDL.hh index 260679a0ae2..606b0157e6c 100644 --- a/intern/ghost/intern/GHOST_ContextSDL.hh +++ b/intern/ghost/intern/GHOST_ContextSDL.hh @@ -31,7 +31,7 @@ class GHOST_ContextSDL : public GHOST_Context { /** * Constructor. */ - GHOST_ContextSDL(bool stereoVisual, + GHOST_ContextSDL(const GHOST_ContextParams &context_params, SDL_Window *window, int contextProfileMask, int contextMajorVersion, diff --git a/intern/ghost/intern/GHOST_ContextVK.cc b/intern/ghost/intern/GHOST_ContextVK.cc index 419a20b701d..3acbe5a1e05 100644 --- a/intern/ghost/intern/GHOST_ContextVK.cc +++ b/intern/ghost/intern/GHOST_ContextVK.cc @@ -554,7 +554,7 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance, /** \} */ -GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual, +GHOST_ContextVK::GHOST_ContextVK(const GHOST_ContextParams &context_params, #ifdef _WIN32 HWND hwnd, #elif defined(__APPLE__) @@ -571,9 +571,8 @@ GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual, #endif int contextMajorVersion, int contextMinorVersion, - int debug, const GHOST_GPUDevice &preferred_device) - : GHOST_Context(stereoVisual), + : GHOST_Context(context_params), #ifdef _WIN32 m_hwnd(hwnd), #elif defined(__APPLE__) @@ -590,7 +589,6 @@ GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual, #endif m_context_major_version(contextMajorVersion), m_context_minor_version(contextMinorVersion), - m_debug(debug), m_preferred_device(preferred_device), m_surface(VK_NULL_HANDLE), m_swapchain(VK_NULL_HANDLE), @@ -857,7 +855,7 @@ static void requireExtension(const vector &extensions_ava } } -static GHOST_TSuccess selectPresentMode(const char *ghost_vsync_string, +static GHOST_TSuccess selectPresentMode(const GHOST_TVSyncModes vsync, VkPhysicalDevice device, VkSurfaceKHR surface, VkPresentModeKHR *r_presentMode) @@ -867,8 +865,8 @@ static GHOST_TSuccess selectPresentMode(const char *ghost_vsync_string, vector presents(present_count); vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_count, presents.data()); - if (ghost_vsync_string) { - bool vsync_off = atoi(ghost_vsync_string) == 0; + if (vsync != GHOST_kVSyncModeUnset) { + const bool vsync_off = (vsync == GHOST_kVSyncModeOff); if (vsync_off) { for (auto present_mode : presents) { if (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) { @@ -877,9 +875,8 @@ static GHOST_TSuccess selectPresentMode(const char *ghost_vsync_string, } } CLOG_WARN(&LOG, - "Vulkan: VSync off was requested via BLENDER_VSYNC, but " - "VK_PRESENT_MODE_IMMEDIATE_KHR is not " - "supported."); + "Vulkan: VSync off was requested via --gpu-vsync, " + "but VK_PRESENT_MODE_IMMEDIATE_KHR is not supported."); } } @@ -984,7 +981,7 @@ GHOST_TSuccess GHOST_ContextVK::recreateSwapchain(bool use_hdr_swapchain) } VkPresentModeKHR present_mode; - if (!selectPresentMode(getEnvVarVSyncString(), physical_device, m_surface, &present_mode)) { + if (!selectPresentMode(getVSync(), physical_device, m_surface, &present_mode)) { return GHOST_kFailure; } @@ -1258,7 +1255,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext() vector optional_device_extensions; vector extensions_enabled; - if (m_debug) { + if (m_context_params.is_debug) { requireExtension(extensions_available, extensions_enabled, VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } diff --git a/intern/ghost/intern/GHOST_ContextVK.hh b/intern/ghost/intern/GHOST_ContextVK.hh index 2ae10dc4892..8b7672165ca 100644 --- a/intern/ghost/intern/GHOST_ContextVK.hh +++ b/intern/ghost/intern/GHOST_ContextVK.hh @@ -109,7 +109,7 @@ class GHOST_ContextVK : public GHOST_Context { /** * Constructor. */ - GHOST_ContextVK(bool stereoVisual, + GHOST_ContextVK(const GHOST_ContextParams &context_params, #ifdef _WIN32 HWND hwnd, #elif defined(__APPLE__) @@ -127,7 +127,6 @@ class GHOST_ContextVK : public GHOST_Context { #endif int contextMajorVersion, int contextMinorVersion, - int debug, const GHOST_GPUDevice &preferred_device); /** @@ -229,7 +228,6 @@ class GHOST_ContextVK : public GHOST_Context { const int m_context_major_version; const int m_context_minor_version; - const int m_debug; const GHOST_GPUDevice m_preferred_device; VkQueue m_graphic_queue; diff --git a/intern/ghost/intern/GHOST_ContextWGL.cc b/intern/ghost/intern/GHOST_ContextWGL.cc index c30fe9da87d..3101b099968 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.cc +++ b/intern/ghost/intern/GHOST_ContextWGL.cc @@ -25,7 +25,7 @@ static bool is_crappy_intel_card() return strstr((const char *)glGetString(GL_VENDOR), "Intel") != nullptr; } -GHOST_ContextWGL::GHOST_ContextWGL(bool stereoVisual, +GHOST_ContextWGL::GHOST_ContextWGL(const GHOST_ContextParams &context_params, bool alphaBackground, HWND hWnd, HDC hDC, @@ -34,7 +34,7 @@ GHOST_ContextWGL::GHOST_ContextWGL(bool stereoVisual, int contextMinorVersion, int contextFlags, int contextResetNotificationStrategy) - : GHOST_Context(stereoVisual), + : GHOST_Context(context_params), m_hWnd(hWnd), m_hDC(hDC), m_contextProfileMask(contextProfileMask), @@ -480,7 +480,7 @@ int GHOST_ContextWGL::choose_pixel_format_arb(bool stereoVisual, bool needAlpha) iPixelFormat = _choose_pixel_format_arb_1(false, needAlpha); - m_stereoVisual = false; // set context property to actual value + m_context_params.is_stereo_visual = false; /* Set context property to actual value. */ } return iPixelFormat; @@ -509,13 +509,13 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext() { const bool needAlpha = m_alphaBackground; - DummyContextWGL dummy(m_hDC, m_hWnd, m_stereoVisual, needAlpha); + DummyContextWGL dummy(m_hDC, m_hWnd, m_context_params.is_stereo_visual, needAlpha); if (!dummy.has_WGL_ARB_create_context || ::GetPixelFormat(m_hDC) == 0) { int iPixelFormat = 0; if (dummy.has_WGL_ARB_pixel_format) { - iPixelFormat = choose_pixel_format_arb(m_stereoVisual, needAlpha); + iPixelFormat = choose_pixel_format_arb(m_context_params.is_stereo_visual, needAlpha); } if (iPixelFormat == 0) { @@ -617,10 +617,9 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext() } { - const char *ghost_vsync_string = getEnvVarVSyncString(); - if (ghost_vsync_string) { - int swapInterval = atoi(ghost_vsync_string); - setSwapInterval(swapInterval); + const GHOST_TVSyncModes vsync = getVSync(); + if (vsync != GHOST_kVSyncModeUnset) { + setSwapInterval(int(vsync)); } } diff --git a/intern/ghost/intern/GHOST_ContextWGL.hh b/intern/ghost/intern/GHOST_ContextWGL.hh index 05e53982c1f..48f15452670 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.hh +++ b/intern/ghost/intern/GHOST_ContextWGL.hh @@ -24,7 +24,7 @@ class GHOST_ContextWGL : public GHOST_Context { /** * Constructor. */ - GHOST_ContextWGL(bool stereoVisual, + GHOST_ContextWGL(const GHOST_ContextParams &context_params, bool alphaBackground, HWND hWnd, HDC hDC, diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 3e653090c3b..40e8807667d 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -725,6 +725,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, const bool is_dialog, const GHOST_IWindow *parentWindow) { + const GHOST_ContextParams context_params = GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpuSettings); GHOST_IWindow *window = nullptr; @autoreleasepool { /* Get the available rect for including window contents. */ @@ -744,8 +745,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, height, state, gpuSettings.context_type, - gpuSettings.flags & GHOST_gpuStereoVisual, - gpuSettings.flags & GHOST_gpuDebugContext, + context_params, is_dialog, (GHOST_WindowCocoa *)parentWindow, gpuSettings.preferred_device); @@ -776,13 +776,14 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, */ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings) { - const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0; + const GHOST_ContextParams context_params_offscreen = + GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpuSettings); switch (gpuSettings.context_type) { #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { GHOST_Context *context = new GHOST_ContextVK( - false, nullptr, 1, 2, debug_context, gpuSettings.preferred_device); + context_params_offscreen, nullptr, 1, 2, gpuSettings.preferred_device); if (context->initializeDrawingContext()) { return context; } @@ -793,7 +794,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuS #ifdef WITH_METAL_BACKEND case GHOST_kDrawingContextTypeMetal: { - GHOST_Context *context = new GHOST_ContextMTL(false, nullptr, nullptr, debug_context); + GHOST_Context *context = new GHOST_ContextMTL(context_params_offscreen, nullptr, nullptr); if (context->initializeDrawingContext()) { return context; } diff --git a/intern/ghost/intern/GHOST_SystemHeadless.hh b/intern/ghost/intern/GHOST_SystemHeadless.hh index 0662191097f..c29c1f69725 100644 --- a/intern/ghost/intern/GHOST_SystemHeadless.hh +++ b/intern/ghost/intern/GHOST_SystemHeadless.hh @@ -111,18 +111,20 @@ class GHOST_SystemHeadless : public GHOST_System { } GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override { + const GHOST_ContextParams context_params_offscreen = + GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpuSettings); + switch (gpuSettings.context_type) { #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { - const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0; # ifdef _WIN32 GHOST_Context *context = new GHOST_ContextVK( - false, (HWND)0, 1, 2, debug_context, gpuSettings.preferred_device); + context_params_offscreen, (HWND)0, 1, 2, gpuSettings.preferred_device); # elif defined(__APPLE__) GHOST_Context *context = new GHOST_ContextVK( - false, nullptr, 1, 2, debug_context, gpuSettings.preferred_device); + context_params_offscreen, nullptr, 1, 2, gpuSettings.preferred_device); # else - GHOST_Context *context = new GHOST_ContextVK(false, + GHOST_Context *context = new GHOST_ContextVK(context_params_offscreen, GHOST_kVulkanPlatformHeadless, 0, 0, @@ -131,7 +133,6 @@ class GHOST_SystemHeadless : public GHOST_System { nullptr, 1, 2, - debug_context, gpuSettings.preferred_device); # endif if (context->initializeDrawingContext()) { @@ -148,7 +149,7 @@ class GHOST_SystemHeadless : public GHOST_System { GHOST_Context *context; for (int minor = 6; minor >= 3; --minor) { context = new GHOST_ContextEGL((GHOST_System *)this, - false, + context_params_offscreen, EGLNativeWindowType(0), EGLNativeDisplayType(EGL_DEFAULT_DISPLAY), EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, @@ -205,6 +206,7 @@ class GHOST_SystemHeadless : public GHOST_System { const bool /*is_dialog*/, const GHOST_IWindow *parentWindow) override { + const GHOST_ContextParams context_params = GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpuSettings); return new GHOST_WindowNULL(title, left, top, @@ -213,7 +215,7 @@ class GHOST_SystemHeadless : public GHOST_System { state, parentWindow, gpuSettings.context_type, - ((gpuSettings.flags & GHOST_gpuStereoVisual) != 0)); + context_params); } GHOST_IWindow *getWindowUnderCursor(int32_t /*x*/, int32_t /*y*/) override diff --git a/intern/ghost/intern/GHOST_SystemSDL.cc b/intern/ghost/intern/GHOST_SystemSDL.cc index 3a8683cad1e..1469cdcb6aa 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cc +++ b/intern/ghost/intern/GHOST_SystemSDL.cc @@ -51,6 +51,8 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, { GHOST_WindowSDL *window = nullptr; + const GHOST_ContextParams context_params = GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpuSettings); + window = new GHOST_WindowSDL(this, title, left, @@ -59,7 +61,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, height, state, gpuSettings.context_type, - ((gpuSettings.flags & GHOST_gpuStereoVisual) != 0), + context_params, exclusive, parentWindow); @@ -131,12 +133,15 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GPUSettings gpuSettings) { + const GHOST_ContextParams context_params_offscreen = + GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpuSettings); + switch (gpuSettings.context_type) { #ifdef WITH_OPENGL_BACKEND case GHOST_kDrawingContextTypeOpenGL: { for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = new GHOST_ContextSDL( - false, + context_params_offscreen, nullptr, 0, /* Profile bit. */ 4, diff --git a/intern/ghost/intern/GHOST_SystemWayland.cc b/intern/ghost/intern/GHOST_SystemWayland.cc index ae787f5d2db..07e489456ce 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cc +++ b/intern/ghost/intern/GHOST_SystemWayland.cc @@ -8584,7 +8584,8 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gp std::lock_guard lock_server_guard{*server_mutex}; #endif - const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0; + const GHOST_ContextParams context_params_offscreen = + GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpuSettings); switch (gpuSettings.context_type) { @@ -8593,7 +8594,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gp /* Create new off-screen surface only for vulkan. */ wl_surface *wl_surface = wl_compositor_create_surface(wl_compositor_get()); - GHOST_Context *context = new GHOST_ContextVK(false, + GHOST_Context *context = new GHOST_ContextVK(context_params_offscreen, GHOST_kVulkanPlatformWayland, 0, nullptr, @@ -8602,7 +8603,6 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gp nullptr, 1, 2, - debug_context, gpuSettings.preferred_device); if (context->initializeDrawingContext()) { @@ -8628,14 +8628,14 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gp /* Caller must lock `system->server_mutex`. */ GHOST_Context *context = new GHOST_ContextEGL( this, - false, + context_params_offscreen, EGLNativeWindowType(egl_window), EGLNativeDisplayType(display_->wl.display), EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, 4, minor, GHOST_OPENGL_EGL_CONTEXT_FLAGS | - (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0), + (context_params_offscreen.is_debug ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0), GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, EGL_OPENGL_API); @@ -8717,22 +8717,22 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, const bool is_dialog, const GHOST_IWindow *parentWindow) { + const GHOST_ContextParams context_params = GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpuSettings); + /* Globally store pointer to window manager. */ - GHOST_WindowWayland *window = new GHOST_WindowWayland( - this, - title, - left, - top, - width, - height, - state, - parentWindow, - gpuSettings.context_type, - is_dialog, - ((gpuSettings.flags & GHOST_gpuStereoVisual) != 0), - exclusive, - (gpuSettings.flags & GHOST_gpuDebugContext) != 0, - gpuSettings.preferred_device); + GHOST_WindowWayland *window = new GHOST_WindowWayland(this, + title, + left, + top, + width, + height, + state, + parentWindow, + gpuSettings.context_type, + is_dialog, + context_params, + exclusive, + gpuSettings.preferred_device); if (window) { if (window->getValid()) { diff --git a/intern/ghost/intern/GHOST_SystemWin32.cc b/intern/ghost/intern/GHOST_SystemWin32.cc index c530fcf8b34..f20e6e27474 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cc +++ b/intern/ghost/intern/GHOST_SystemWin32.cc @@ -271,20 +271,19 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, const bool is_dialog, const GHOST_IWindow *parentWindow) { - GHOST_WindowWin32 *window = new GHOST_WindowWin32( - this, - title, - left, - top, - width, - height, - state, - gpuSettings.context_type, - ((gpuSettings.flags & GHOST_gpuStereoVisual) != 0), - (GHOST_WindowWin32 *)parentWindow, - ((gpuSettings.flags & GHOST_gpuDebugContext) != 0), - is_dialog, - gpuSettings.preferred_device); + const GHOST_ContextParams context_params = GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpuSettings); + GHOST_WindowWin32 *window = new GHOST_WindowWin32(this, + title, + left, + top, + width, + height, + state, + gpuSettings.context_type, + context_params, + (GHOST_WindowWin32 *)parentWindow, + is_dialog, + gpuSettings.preferred_device); if (window->getValid()) { /* Store the pointer to the window */ @@ -307,13 +306,14 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, */ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GPUSettings gpuSettings) { - const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0; + const GHOST_ContextParams context_params_offscreen = + GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpuSettings); switch (gpuSettings.context_type) { #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { GHOST_Context *context = new GHOST_ContextVK( - false, (HWND)0, 1, 2, debug_context, gpuSettings.preferred_device); + context_params_offscreen, (HWND)0, 1, 2, gpuSettings.preferred_device); if (context->initializeDrawingContext()) { return context; } @@ -344,14 +344,14 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GPUSettings gpuS for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = new GHOST_ContextWGL( - false, + context_params_offscreen, true, wnd, mHDC, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 4, minor, - (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0), + (context_params_offscreen.is_debug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0), GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY); if (context->initializeDrawingContext()) { @@ -389,6 +389,8 @@ GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context) */ GHOST_ContextD3D *GHOST_SystemWin32::createOffscreenContextD3D() { + /* NOTE: the `gpuSettings` could be passed in here, as it is with similar functions. */ + const GHOST_ContextParams context_params_offscreen = GHOST_CONTEXT_PARAMS_NONE; HWND wnd = CreateWindowA("STATIC", "Blender XR", WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, @@ -401,7 +403,7 @@ GHOST_ContextD3D *GHOST_SystemWin32::createOffscreenContextD3D() GetModuleHandle(nullptr), nullptr); - GHOST_ContextD3D *context = new GHOST_ContextD3D(false, wnd); + GHOST_ContextD3D *context = new GHOST_ContextD3D(context_params_offscreen, wnd); if (context->initializeDrawingContext()) { return context; } diff --git a/intern/ghost/intern/GHOST_SystemX11.cc b/intern/ghost/intern/GHOST_SystemX11.cc index e571592a0c2..c108636f594 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cc +++ b/intern/ghost/intern/GHOST_SystemX11.cc @@ -366,6 +366,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, return nullptr; } + const GHOST_ContextParams context_params = GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpuSettings); window = new GHOST_WindowX11(this, m_display, title, @@ -377,9 +378,8 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, (GHOST_WindowX11 *)parentWindow, gpuSettings.context_type, is_dialog, - ((gpuSettings.flags & GHOST_gpuStereoVisual) != 0), + context_params, exclusive, - (gpuSettings.flags & GHOST_gpuDebugContext) != 0, gpuSettings.preferred_device); if (window) { @@ -402,11 +402,13 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSettings) { - const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0; + const GHOST_ContextParams context_params_offscreen = + GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpuSettings); + switch (gpuSettings.context_type) { #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { - GHOST_Context *context = new GHOST_ContextVK(false, + GHOST_Context *context = new GHOST_ContextVK(context_params_offscreen, GHOST_kVulkanPlatformX11, 0, m_display, @@ -415,7 +417,6 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSet nullptr, 1, 2, - debug_context, gpuSettings.preferred_device); if (context->initializeDrawingContext()) { return context; @@ -429,14 +430,15 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSet case GHOST_kDrawingContextTypeOpenGL: { for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = new GHOST_ContextGLX( - false, + context_params_offscreen, (Window) nullptr, m_display, (GLXFBConfig) nullptr, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 4, minor, - GHOST_OPENGL_GLX_CONTEXT_FLAGS | (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), + GHOST_OPENGL_GLX_CONTEXT_FLAGS | + (context_params_offscreen.is_debug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); if (context->initializeDrawingContext()) { return context; diff --git a/intern/ghost/intern/GHOST_Window.cc b/intern/ghost/intern/GHOST_Window.cc index 3d09e696df6..c944040347c 100644 --- a/intern/ghost/intern/GHOST_Window.cc +++ b/intern/ghost/intern/GHOST_Window.cc @@ -19,7 +19,7 @@ GHOST_Window::GHOST_Window(uint32_t width, uint32_t height, GHOST_TWindowState state, - const bool wantStereoVisual, + const GHOST_ContextParams &context_params, const bool /*exclusive*/) : m_drawingContextType(GHOST_kDrawingContextTypeNone), m_userData(nullptr), @@ -34,11 +34,13 @@ GHOST_Window::GHOST_Window(uint32_t width, m_isUnsavedChanges(false), m_windowDecorationStyleFlags(GHOST_kDecorationNone), m_windowDecorationStyleSettings(), - m_wantStereoVisual(wantStereoVisual), + m_want_context_params(context_params), m_nativePixelSize(1.0f), - m_context(new GHOST_ContextNone(false)) + m_context(nullptr) { + const GHOST_ContextParams context_params_none = GHOST_CONTEXT_PARAMS_NONE; + m_context = new GHOST_ContextNone(context_params_none); m_fullScreen = state == GHOST_kWindowStateFullScreen; if (m_fullScreen) { @@ -86,7 +88,7 @@ GHOST_TSuccess GHOST_Window::setDrawingContextType(GHOST_TDrawingContextType typ m_drawingContextType = type; } else { - m_context = new GHOST_ContextNone(m_wantStereoVisual); + m_context = new GHOST_ContextNone(m_want_context_params); m_drawingContextType = GHOST_kDrawingContextTypeNone; } diff --git a/intern/ghost/intern/GHOST_Window.hh b/intern/ghost/intern/GHOST_Window.hh index a35cc113c88..c595eee0f5a 100644 --- a/intern/ghost/intern/GHOST_Window.hh +++ b/intern/ghost/intern/GHOST_Window.hh @@ -35,7 +35,7 @@ class GHOST_Window : public GHOST_IWindow { GHOST_Window(uint32_t width, uint32_t height, GHOST_TWindowState state, - const bool wantStereoVisual = false, + const GHOST_ContextParams &context_params, const bool exclusive = false); /** @@ -347,8 +347,8 @@ class GHOST_Window : public GHOST_IWindow { GHOST_TWindowDecorationStyleFlags m_windowDecorationStyleFlags; GHOST_WindowDecorationStyleSettings m_windowDecorationStyleSettings; - /** Whether to attempt to initialize a context with a stereo frame-buffer. */ - bool m_wantStereoVisual; + /** The desired parameters to use when initializing the context for this window. */ + GHOST_ContextParams m_want_context_params; /** Full-screen width */ uint32_t m_fullScreenWidth; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.hh b/intern/ghost/intern/GHOST_WindowCocoa.hh index 7f2b580241e..2cf3aeb4610 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.hh +++ b/intern/ghost/intern/GHOST_WindowCocoa.hh @@ -41,7 +41,7 @@ class GHOST_WindowCocoa : public GHOST_Window { * \param height: The height the window. * \param state: The state the window is initially opened with. * \param type: The type of drawing context installed in this window. - * \param stereoVisual: Stereo visual for quad buffered stereo. + * \param context_params: Parameters to use when initializing the context. * \param preferred_device: Preferred device to use when new device will be created. */ GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, @@ -52,8 +52,7 @@ class GHOST_WindowCocoa : public GHOST_Window { uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, - bool is_debug, + const GHOST_ContextParams &context_params, bool dialog, GHOST_WindowCocoa *parentWindow, const GHOST_GPUDevice &preferred_device); @@ -313,7 +312,6 @@ class GHOST_WindowCocoa : public GHOST_Window { GHOST_TabletData m_tablet; bool m_immediateDraw; - bool m_debug_context; // for debug messages during context setup bool m_is_dialog; GHOST_GPUDevice m_preferred_device; }; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 23dde7a8f23..75d5a8aee3c 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -327,19 +327,17 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, - bool is_debug, + const GHOST_ContextParams &context_params, bool is_dialog, GHOST_WindowCocoa *parentWindow, const GHOST_GPUDevice &preferred_device) - : GHOST_Window(width, height, state, stereoVisual, false), + : GHOST_Window(width, height, state, context_params, false), m_openGLView(nil), m_metalView(nil), m_metalLayer(nil), m_systemCocoa(systemCocoa), m_customCursor(nullptr), m_immediateDraw(false), - m_debug_context(is_debug), m_is_dialog(is_dialog), m_preferred_device(preferred_device) { @@ -900,7 +898,7 @@ GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType ty #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { GHOST_Context *context = new GHOST_ContextVK( - m_wantStereoVisual, m_metalLayer, 1, 2, true, m_preferred_device); + m_want_context_params, m_metalLayer, 1, 2, true, m_preferred_device); if (context->initializeDrawingContext()) { return context; } @@ -912,7 +910,7 @@ GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType ty #ifdef WITH_METAL_BACKEND case GHOST_kDrawingContextTypeMetal: { GHOST_Context *context = new GHOST_ContextMTL( - m_wantStereoVisual, m_metalView, m_metalLayer, false); + m_want_context_params, m_metalView, m_metalLayer); if (context->initializeDrawingContext()) { return context; } diff --git a/intern/ghost/intern/GHOST_WindowNULL.hh b/intern/ghost/intern/GHOST_WindowNULL.hh index de2b0d6c87e..490c43853af 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.hh +++ b/intern/ghost/intern/GHOST_WindowNULL.hh @@ -30,8 +30,8 @@ class GHOST_WindowNULL : public GHOST_Window { GHOST_TWindowState state, const GHOST_IWindow * /*parentWindow*/, GHOST_TDrawingContextType /*type*/, - const bool stereoVisual) - : GHOST_Window(width, height, state, stereoVisual, false) + const GHOST_ContextParams &context_params) + : GHOST_Window(width, height, state, context_params, false) { } diff --git a/intern/ghost/intern/GHOST_WindowSDL.cc b/intern/ghost/intern/GHOST_WindowSDL.cc index 2e6c8b198b2..e9e33df0289 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cc +++ b/intern/ghost/intern/GHOST_WindowSDL.cc @@ -21,10 +21,10 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, + const GHOST_ContextParams &context_params, const bool exclusive, const GHOST_IWindow * /*parentWindow*/) - : GHOST_Window(width, height, state, stereoVisual, exclusive), + : GHOST_Window(width, height, state, context_params, exclusive), m_system(system), m_valid_setup(false), m_invalid_window(false), @@ -65,12 +65,13 @@ GHOST_WindowSDL::~GHOST_WindowSDL() GHOST_Context *GHOST_WindowSDL::newDrawingContext(GHOST_TDrawingContextType type) { + switch (type) { #ifdef WITH_OPENGL_BACKEND case GHOST_kDrawingContextTypeOpenGL: { for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = new GHOST_ContextSDL( - m_wantStereoVisual, + m_want_context_params, m_sdl_win, 0, /* Profile bit. */ 4, diff --git a/intern/ghost/intern/GHOST_WindowSDL.hh b/intern/ghost/intern/GHOST_WindowSDL.hh index ab9000d2713..abe47f58684 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.hh +++ b/intern/ghost/intern/GHOST_WindowSDL.hh @@ -41,8 +41,8 @@ class GHOST_WindowSDL : public GHOST_Window { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false, + GHOST_TDrawingContextType type, + const GHOST_ContextParams &context_params, const bool exclusive = false, const GHOST_IWindow *parentWindow = nullptr); diff --git a/intern/ghost/intern/GHOST_WindowWayland.cc b/intern/ghost/intern/GHOST_WindowWayland.cc index 9186ac20408..49234979a4c 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cc +++ b/intern/ghost/intern/GHOST_WindowWayland.cc @@ -1734,14 +1734,12 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, const GHOST_IWindow *parentWindow, const GHOST_TDrawingContextType type, const bool is_dialog, - const bool stereoVisual, + const GHOST_ContextParams &context_params, const bool exclusive, - const bool is_debug, const GHOST_GPUDevice &preferred_device) - : GHOST_Window(width, height, state, stereoVisual, exclusive), + : GHOST_Window(width, height, state, context_params, exclusive), system_(system), window_(new GWL_Window), - is_debug_context_(is_debug), preferred_device_(preferred_device) { #ifdef USE_EVENT_BACKGROUND_THREAD @@ -2459,13 +2457,13 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType { switch (type) { case GHOST_kDrawingContextTypeNone: { - GHOST_Context *context = new GHOST_ContextNone(m_wantStereoVisual); + GHOST_Context *context = new GHOST_ContextNone(m_want_context_params); return context; } #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { - GHOST_ContextVK *context = new GHOST_ContextVK(m_wantStereoVisual, + GHOST_ContextVK *context = new GHOST_ContextVK(m_want_context_params, GHOST_kVulkanPlatformWayland, 0, nullptr, @@ -2474,7 +2472,6 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType window_->backend.vulkan_window_info, 1, 2, - is_debug_context_, preferred_device_); if (context->initializeDrawingContext()) { return context; @@ -2489,14 +2486,14 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = new GHOST_ContextEGL( system_, - m_wantStereoVisual, + m_want_context_params, EGLNativeWindowType(window_->backend.egl_window), EGLNativeDisplayType(system_->wl_display_get()), EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, 4, minor, GHOST_OPENGL_EGL_CONTEXT_FLAGS | - (is_debug_context_ ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0), + (m_want_context_params.is_debug ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0), GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, EGL_OPENGL_API); diff --git a/intern/ghost/intern/GHOST_WindowWayland.hh b/intern/ghost/intern/GHOST_WindowWayland.hh index 4395f47db7d..02e39cbce16 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.hh +++ b/intern/ghost/intern/GHOST_WindowWayland.hh @@ -76,9 +76,8 @@ class GHOST_WindowWayland : public GHOST_Window { const GHOST_IWindow *parentWindow, GHOST_TDrawingContextType type, const bool is_dialog, - const bool stereoVisual, + const GHOST_ContextParams &context_params, const bool exclusive, - const bool is_debug, const GHOST_GPUDevice &preferred_device); ~GHOST_WindowWayland() override; @@ -202,7 +201,6 @@ class GHOST_WindowWayland : public GHOST_Window { private: GHOST_SystemWayland *system_; struct GWL_Window *window_; - bool is_debug_context_; GHOST_GPUDevice preferred_device_; /** diff --git a/intern/ghost/intern/GHOST_WindowWin32.cc b/intern/ghost/intern/GHOST_WindowWin32.cc index ceedd79ab08..741edd78308 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cc +++ b/intern/ghost/intern/GHOST_WindowWin32.cc @@ -59,12 +59,11 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool wantStereoVisual, + const GHOST_ContextParams &context_params, GHOST_WindowWin32 *parentwindow, - bool is_debug, bool dialog, const GHOST_GPUDevice &preferred_device) - : GHOST_Window(width, height, state, wantStereoVisual, false), + : GHOST_Window(width, height, state, context_params, false), m_mousePresent(false), m_inLiveResize(false), m_system(system), @@ -83,8 +82,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_normal_state(GHOST_kWindowStateNormal), m_user32(::LoadLibrary("user32.dll")), m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP), - m_directManipulationHelper(nullptr), - m_debug_context(is_debug) + m_directManipulationHelper(nullptr) { DWORD style = parentwindow ? WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX : @@ -622,7 +620,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { GHOST_Context *context = new GHOST_ContextVK( - false, m_hWnd, 1, 2, m_debug_context, m_preferred_device); + m_want_context_params, m_hWnd, 1, 2, m_preferred_device); if (context->initializeDrawingContext()) { return context; } @@ -635,14 +633,14 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty case GHOST_kDrawingContextTypeOpenGL: { for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = new GHOST_ContextWGL( - m_wantStereoVisual, + m_want_context_params, false, m_hWnd, m_hDC, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 4, minor, - (m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0), + (m_want_context_params.is_debug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0), GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY); if (context->initializeDrawingContext()) { @@ -655,7 +653,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty #endif case GHOST_kDrawingContextTypeD3D: { - GHOST_Context *context = new GHOST_ContextD3D(false, m_hWnd); + GHOST_Context *context = new GHOST_ContextD3D(m_want_context_params, m_hWnd); if (context->initializeDrawingContext()) { return context; diff --git a/intern/ghost/intern/GHOST_WindowWin32.hh b/intern/ghost/intern/GHOST_WindowWin32.hh index 3b4629c7d41..d9e6fa40d90 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.hh +++ b/intern/ghost/intern/GHOST_WindowWin32.hh @@ -76,9 +76,8 @@ class GHOST_WindowWin32 : public GHOST_Window { uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool wantStereoVisual, + const GHOST_ContextParams &context_params, GHOST_WindowWin32 *parentWindow, - bool is_debug, bool dialog, const GHOST_GPUDevice &preferred_device); @@ -417,5 +416,4 @@ class GHOST_WindowWin32 : public GHOST_Window { /** Handle input method editors event */ GHOST_ImeWin32 m_imeInput; #endif - bool m_debug_context; }; diff --git a/intern/ghost/intern/GHOST_WindowX11.cc b/intern/ghost/intern/GHOST_WindowX11.cc index 7c7c718b97c..a28de4bfa6a 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cc +++ b/intern/ghost/intern/GHOST_WindowX11.cc @@ -110,11 +110,10 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, GHOST_WindowX11 *parentWindow, GHOST_TDrawingContextType type, const bool is_dialog, - const bool stereoVisual, + const GHOST_ContextParams &context_params, const bool exclusive, - const bool is_debug, const GHOST_GPUDevice &preferred_device) - : GHOST_Window(width, height, state, stereoVisual, exclusive), + : GHOST_Window(width, height, state, context_params, exclusive), m_display(display), m_visualInfo(nullptr), m_fbconfig(nullptr), @@ -132,7 +131,6 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, m_xic(nullptr), #endif m_valid_setup(false), - m_is_debug_context(is_debug), m_preferred_device(preferred_device) { #ifdef WITH_OPENGL_BACKEND @@ -1190,7 +1188,7 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type switch (type) { #ifdef WITH_VULKAN_BACKEND case GHOST_kDrawingContextTypeVulkan: { - GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual, + GHOST_Context *context = new GHOST_ContextVK(m_want_context_params, GHOST_kVulkanPlatformX11, m_window, m_display, @@ -1199,7 +1197,6 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type nullptr, 1, 2, - m_is_debug_context, m_preferred_device); if (context->initializeDrawingContext()) { return context; @@ -1216,14 +1213,14 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = GHOST_ContextEGL( this->m_system, - m_wantStereoVisual, + m_want_context_params, EGLNativeWindowType(m_window), EGLNativeDisplayType(m_display), EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, 4, minor, GHOST_OPENGL_EGL_CONTEXT_FLAGS | - (m_is_debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0), + (m_want_context_params.is_debug ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0), GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, EGL_OPENGL_API); if (context->initializeDrawingContext()) { @@ -1236,14 +1233,15 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type for (int minor = 6; minor >= 3; --minor) { GHOST_Context *context = new GHOST_ContextGLX( - m_wantStereoVisual, + m_want_context_params, m_window, m_display, (GLXFBConfig)m_fbconfig, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 4, minor, - GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), + GHOST_OPENGL_GLX_CONTEXT_FLAGS | + (m_want_context_params.is_debug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); if (context->initializeDrawingContext()) { return context; diff --git a/intern/ghost/intern/GHOST_WindowX11.hh b/intern/ghost/intern/GHOST_WindowX11.hh index b7f77e10ad9..29bbd340ab8 100644 --- a/intern/ghost/intern/GHOST_WindowX11.hh +++ b/intern/ghost/intern/GHOST_WindowX11.hh @@ -44,7 +44,7 @@ class GHOST_WindowX11 : public GHOST_Window { * \param state: The state the window is initially opened with. * \param parentWindow: Parent (embedder) window. * \param type: The type of drawing context installed in this window. - * \param stereoVisual: Stereo visual for quad buffered stereo. + * \param context_params: Parameters to use when initializing the context. * \param preferred_device: Preferred device to use when new device will be created. */ GHOST_WindowX11(GHOST_SystemX11 *system, @@ -58,9 +58,8 @@ class GHOST_WindowX11 : public GHOST_Window { GHOST_WindowX11 *parentWindow, GHOST_TDrawingContextType type, const bool is_dialog, - const bool stereoVisual, + const GHOST_ContextParams &context_params, const bool exclusive, - const bool is_debug, const GHOST_GPUDevice &preferred_device); bool getValid() const override; @@ -241,7 +240,6 @@ class GHOST_WindowX11 : public GHOST_Window { #endif bool m_valid_setup; - bool m_is_debug_context; GHOST_GPUDevice m_preferred_device; void icccmSetState(int state); diff --git a/source/blender/gpu/GPU_context.hh b/source/blender/gpu/GPU_context.hh index ff37057db7f..7366ad0efd6 100644 --- a/source/blender/gpu/GPU_context.hh +++ b/source/blender/gpu/GPU_context.hh @@ -46,6 +46,18 @@ void GPU_backend_type_selection_set_override(eGPUBackendType backend_type); */ bool GPU_backend_type_selection_is_overridden(); +/** + * Get the VSync value (when set). + */ +int GPU_backend_vsync_get(); +/** + * Override the default VSync. + * + * \param vsync: See #GHOST_TVSyncModes for details. + */ +void GPU_backend_vsync_set_override(int vsync); +bool GPU_backend_vsync_is_overridden(); + /** Opaque type hiding blender::gpu::Context. */ struct GPUContext; diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index 507c485c35b..fa45371a773 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -343,6 +343,7 @@ void GPU_render_step(bool force_resource_release) static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; static std::optional g_backend_type_override = std::nullopt; static std::optional g_backend_type_supported = std::nullopt; +static std::optional g_vsync_override = std::nullopt; static GPUBackend *g_backend = nullptr; static GHOST_SystemHandle g_ghost_system = nullptr; @@ -362,6 +363,21 @@ void GPU_backend_type_selection_set(const eGPUBackendType backend) g_backend_type_supported = std::nullopt; } +int GPU_backend_vsync_get() +{ + return g_vsync_override.value(); +} + +void GPU_backend_vsync_set_override(const int vsync) +{ + g_vsync_override = vsync; +} + +bool GPU_backend_vsync_is_overridden() +{ + return g_vsync_override.has_value(); +} + eGPUBackendType GPU_backend_type_selection_get() { return g_backend_type; diff --git a/source/blender/windowmanager/intern/wm_playanim.cc b/source/blender/windowmanager/intern/wm_playanim.cc index 6bdaabe0d8c..e601b7321c7 100644 --- a/source/blender/windowmanager/intern/wm_playanim.cc +++ b/source/blender/windowmanager/intern/wm_playanim.cc @@ -1596,6 +1596,10 @@ static GHOST_WindowHandle playanim_window_open( gpusettings.preferred_device.index = U.gpu_preferred_index; gpusettings.preferred_device.vendor_id = U.gpu_preferred_vendor_id; gpusettings.preferred_device.device_id = U.gpu_preferred_device_id; + if (GPU_backend_vsync_is_overridden()) { + gpusettings.flags |= GHOST_gpuVSyncIsOverridden; + gpusettings.vsync = GHOST_TVSyncModes(GPU_backend_vsync_get()); + } { bool screen_size_valid = false; diff --git a/source/blender/windowmanager/intern/wm_window.cc b/source/blender/windowmanager/intern/wm_window.cc index d9b1825483a..d24c0e4f666 100644 --- a/source/blender/windowmanager/intern/wm_window.cc +++ b/source/blender/windowmanager/intern/wm_window.cc @@ -880,6 +880,10 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, gpuSettings.preferred_device.index = U.gpu_preferred_index; gpuSettings.preferred_device.vendor_id = U.gpu_preferred_vendor_id; gpuSettings.preferred_device.device_id = U.gpu_preferred_device_id; + if (GPU_backend_vsync_is_overridden()) { + gpuSettings.flags |= GHOST_gpuVSyncIsOverridden; + gpuSettings.vsync = GHOST_TVSyncModes(GPU_backend_vsync_get()); + } int posx = 0; int posy = 0; @@ -3160,6 +3164,10 @@ void *WM_system_gpu_context_create() gpuSettings.preferred_device.index = U.gpu_preferred_index; gpuSettings.preferred_device.vendor_id = U.gpu_preferred_vendor_id; gpuSettings.preferred_device.device_id = U.gpu_preferred_device_id; + if (GPU_backend_vsync_is_overridden()) { + gpuSettings.flags |= GHOST_gpuVSyncIsOverridden; + gpuSettings.vsync = GHOST_TVSyncModes(GPU_backend_vsync_get()); + } return GHOST_CreateGPUContext(g_system, gpuSettings); } diff --git a/source/creator/creator_args.cc b/source/creator/creator_args.cc index c9a3306558d..e883dfcec57 100644 --- a/source/creator/creator_args.cc +++ b/source/creator/creator_args.cc @@ -784,6 +784,7 @@ static void print_help(bArgs *ba, bool all) PRINT("\n"); PRINT("GPU Options:\n"); BLI_args_print_arg_doc(ba, "--gpu-backend"); + BLI_args_print_arg_doc(ba, "--gpu-vsync"); if (defs.with_opengl_backend) { BLI_args_print_arg_doc(ba, "--gpu-compilation-subprocesses"); } @@ -871,9 +872,6 @@ static void print_help(bArgs *ba, bool all) PRINT(" $BLENDER_CUSTOM_SPLASH Full path to an image that replaces the splash screen.\n"); PRINT( " $BLENDER_CUSTOM_SPLASH_BANNER Full path to an image to overlay on the splash screen.\n"); - PRINT( - " $BLENDER_VSYNC Set to 0 to disable VSync.\n" - " With OpenGL, other values set the swap interval.\n"); if (defs.with_opencolorio) { PRINT(" $OCIO Path to override the OpenColorIO configuration file.\n"); @@ -1614,6 +1612,44 @@ static int arg_handle_gpu_backend_set(int argc, const char **argv, void * /*data return 1; } +static const char arg_handle_gpu_vsync_set_doc[] = + "\n" + "\tSet the VSync.\n" + "\tValid options are: 'on', 'off' & 'auto' for adaptive sync.\n" + "\n" + "\t* The default settings depend on the GPU driver.\n" + "\t* Disabling VSync can be useful for testing performance.\n" + "\t* 'auto' is only supported by the OpenGL backend."; +static int arg_handle_gpu_vsync_set(int argc, const char **argv, void * /*data*/) +{ + const char *arg_id = "--gpu-vsync"; + + if (argc < 2) { + fprintf(stderr, "\nError: VSync value must follow '%s'.\n", arg_id); + return 0; + } + + /* Must be compatible with #GHOST_TVSyncModes. */ + int vsync; + if (STREQ(argv[1], "on")) { + vsync = 1; + } + else if (STREQ(argv[1], "off")) { + vsync = 0; + } + else if (STREQ(argv[1], "auto")) { + vsync = -1; + } + else { + fprintf(stderr, "\nError: expected a value in [on, off, auto] '%s %s'.\n", arg_id, argv[1]); + return 0; + } + + GPU_backend_vsync_set_override(vsync); + + return 1; +} + static const char arg_handle_gpu_compilation_subprocesses_set_doc[] = "\n" "\tOverride the Max Compilation Subprocesses setting (OpenGL only)."; @@ -2758,6 +2794,7 @@ void main_args_setup(bContext *C, bArgs *ba, bool all) /* GPU backend selection should be part of #ARG_PASS_ENVIRONMENT for correct GPU context * selection for animation player. */ BLI_args_add(ba, nullptr, "--gpu-backend", CB_ALL(arg_handle_gpu_backend_set), nullptr); + BLI_args_add(ba, nullptr, "--gpu-vsync", CB(arg_handle_gpu_vsync_set), nullptr); if (defs.with_opengl_backend) { BLI_args_add(ba, nullptr,