UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
106 changed files with 1861 additions and 764 deletions
Showing only changes of commit 9e339152ff - Show all commits

View File

@ -162,7 +162,7 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param glSettings: Misc OpenGL options.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new window ( == NULL if creation failed).
*/
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
@ -174,17 +174,17 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_GLSettings glSettings);
GHOST_GPUSettings gpuSettings);
/**
* Create a new off-screen context.
* Never explicitly delete the context, use #disposeContext() instead.
* \param systemhandle: The handle to the system.
* \param glSettings: Misc OpenGL options.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new context ( == NULL if creation failed).
*/
extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_GLSettings glSettings);
extern GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.
@ -192,8 +192,8 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
* \param contexthandle: Handle to the context to be disposed.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle);
/**
* Returns the window user data.
@ -730,24 +730,24 @@ extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
* \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle);
/**
* Release the drawing context bound to this thread.
* \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle);
/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
*/
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
extern unsigned int GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle);
/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
*/
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle);
extern unsigned int GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle);
/**
* Use multi-touch gestures if supported.
@ -1072,7 +1072,7 @@ int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
/**
* Check if \a xr_context has a session that requires an upside-down frame-buffer (compared to
* OpenGL). If true, the render result should be flipped vertically for correct output.
* GPU). If true, the render result should be flipped vertically for correct output.
* \note Only to be called after session start, may otherwise result in a false negative.
*/
int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context);

View File

@ -230,7 +230,7 @@ class GHOST_ISystem {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param parentWindow: Parent (embedder) window
@ -242,7 +242,7 @@ class GHOST_ISystem {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL) = 0;
@ -259,7 +259,7 @@ class GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
/**
* Dispose of a context.

View File

@ -64,9 +64,9 @@ typedef struct {
} GHOST_CursorBitmapRef;
typedef enum {
GHOST_glStereoVisual = (1 << 0),
GHOST_glDebugContext = (1 << 1),
} GHOST_GLFlags;
GHOST_gpuStereoVisual = (1 << 0),
GHOST_gpuDebugContext = (1 << 1),
} GHOST_GPUFlags;
typedef enum GHOST_DialogOptions {
GHOST_DialogWarning = (1 << 0),
@ -681,7 +681,7 @@ typedef struct {
typedef struct {
int flags;
GHOST_TDrawingContextType context_type;
} GHOST_GLSettings;
} GHOST_GPUSettings;
typedef enum {
/** Axis that cursor grab will wrap. */

View File

@ -135,16 +135,16 @@ void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
system->getAllDisplayDimensions(*width, *height);
}
GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_GLSettings glSettings)
GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
GHOST_GPUSettings gpuSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
return (GHOST_ContextHandle)system->createOffscreenContext(glSettings);
return (GHOST_ContextHandle)system->createOffscreenContext(gpuSettings);
}
GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
@ -161,7 +161,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_GLSettings glSettings)
GHOST_GPUSettings gpuSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@ -171,7 +171,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
width,
height,
state,
glSettings,
gpuSettings,
false,
is_dialog,
(GHOST_IWindow *)parent_windowhandle);
@ -716,7 +716,7 @@ GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandl
return window->activateDrawingContext();
}
GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
if (context) {
@ -726,21 +726,21 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
return context->releaseDrawingContext();
}
uint GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle)
uint GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
return context->getDefaultFramebuffer();
}
uint GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
uint GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;

View File

@ -397,12 +397,12 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
const GHOST_DisplaySetting &settings,
const bool stereoVisual)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
if (stereoVisual) {
glSettings.flags |= GHOST_glStereoVisual;
gpuSettings.flags |= GHOST_gpuStereoVisual;
}
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
/* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger than the viewport. */
GHOST_ASSERT(m_displayManager,
@ -414,7 +414,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
settings.xPixels,
settings.yPixels,
GHOST_kWindowStateNormal,
glSettings,
gpuSettings,
true /* exclusive */);
return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
}

View File

@ -101,7 +101,7 @@ class GHOST_System : public GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
/**
* Returns whether a window is valid.

View File

@ -77,7 +77,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
* \return The new window (or 0 if creation failed).
@ -88,7 +88,7 @@ class GHOST_SystemCocoa : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL);
@ -98,7 +98,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.

View File

@ -696,7 +696,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -725,9 +725,9 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
glSettings.flags & GHOST_glStereoVisual,
glSettings.flags & GHOST_glDebugContext,
gpuSettings.context_type,
gpuSettings.flags & GHOST_gpuStereoVisual,
gpuSettings.flags & GHOST_gpuDebugContext,
is_dialog,
(GHOST_WindowCocoa *)parentWindow);
@ -755,11 +755,11 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
#ifdef WITH_VULKAN_BACKEND
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 2, debug_context);
if (!context->initializeDrawingContext()) {
delete context;
@ -769,7 +769,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSet
}
#endif
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type);
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, gpuSettings.context_type);
if (context->initializeDrawingContext())
return context;
else

View File

@ -79,7 +79,7 @@ class GHOST_SystemHeadless : public GHOST_System {
void getAllDisplayDimensions(uint32_t & /*width*/, uint32_t & /*height*/) const override
{ /* nop */
}
GHOST_IContext *createOffscreenContext(GHOST_GLSettings /*glSettings*/) override
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/) override
{
#ifdef __linux__
GHOST_Context *context;
@ -150,7 +150,7 @@ class GHOST_SystemHeadless : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool /*exclusive*/,
const bool /*is_dialog*/,
const GHOST_IWindow *parentWindow) override
@ -162,8 +162,8 @@ class GHOST_SystemHeadless : public GHOST_System {
height,
state,
parentWindow,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0));
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0));
}
GHOST_IWindow *getWindowUnderCursor(int32_t /*x*/, int32_t /*y*/) override

View File

@ -42,7 +42,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool /* is_dialog */,
const GHOST_IWindow *parentWindow)
@ -56,8 +56,8 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive,
parentWindow);
@ -125,7 +125,7 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const
return SDL_GetNumVideoDisplays();
}
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/)
{
GHOST_Context *context = new GHOST_ContextSDL(false,
nullptr,

View File

@ -60,7 +60,7 @@ class GHOST_SystemSDL : public GHOST_System {
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
@ -73,7 +73,7 @@ class GHOST_SystemSDL : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = nullptr) override;

View File

@ -6279,7 +6279,7 @@ static GHOST_Context *createOffscreenContext_impl(GHOST_SystemWayland *system,
return nullptr;
}
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
#ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_server_guard{*server_mutex};
@ -6289,9 +6289,9 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
wl_surface *wl_surface = wl_compositor_create_surface(wl_compositor());
#ifdef WITH_VULKAN_BACKEND
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(false,
GHOST_kVulkanPlatformWayland,
0,
@ -6310,7 +6310,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
return context;
}
#else
(void)glSettings;
(void)gpuSettings;
#endif
wl_egl_window *egl_window = wl_surface ? wl_egl_window_create(wl_surface, 1, 1) : nullptr;
@ -6359,7 +6359,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
const uint32_t width,
const uint32_t height,
const GHOST_TWindowState state,
const GHOST_GLSettings glSettings,
const GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -6374,9 +6374,9 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
height,
state,
parentWindow,
glSettings.context_type,
gpuSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive);
if (window) {

View File

@ -157,7 +157,7 @@ class GHOST_SystemWayland : public GHOST_System {
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
@ -167,7 +167,7 @@ class GHOST_SystemWayland : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow) override;

View File

@ -224,7 +224,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool /*exclusive*/,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -237,11 +237,11 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
false,
(GHOST_WindowWin32 *)parentWindow,
((glSettings.flags & GHOST_glDebugContext) != 0),
((gpuSettings.flags & GHOST_gpuDebugContext) != 0),
is_dialog);
if (window->getValid()) {
@ -263,15 +263,15 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = nullptr;
#ifdef WITH_VULKAN_BACKEND
/* Vulkan does not need a window. */
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
context = new GHOST_ContextVK(false, (HWND)0, 1, 2, debug_context);
if (!context->initializeDrawingContext()) {

View File

@ -103,7 +103,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
* \return The new window (or 0 if creation failed).
@ -114,7 +114,7 @@ class GHOST_SystemWin32 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = 0);
@ -124,7 +124,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.

View File

@ -304,7 +304,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -324,11 +324,11 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
height,
state,
(GHOST_WindowX11 *)parentWindow,
glSettings.context_type,
gpuSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive,
(glSettings.flags & GHOST_glDebugContext) != 0);
(gpuSettings.flags & GHOST_gpuDebugContext) != 0);
if (window) {
/* Both are now handle in GHOST_WindowX11.cc
@ -399,7 +399,7 @@ static GHOST_Context *create_glx_context(Display *display,
return nullptr;
}
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
/* During development:
* try 4.x compatibility profile
@ -411,11 +411,11 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
* try 3.3 core profile
* no fall-backs. */
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = nullptr;
#ifdef WITH_VULKAN_BACKEND
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
context = new GHOST_ContextVK(
false, GHOST_kVulkanPlatformX11, 0, m_display, NULL, NULL, 1, 2, debug_context);

View File

@ -124,7 +124,7 @@ class GHOST_SystemX11 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = nullptr) override;
@ -134,7 +134,7 @@ class GHOST_SystemX11 : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
/**
* Dispose of a context.

View File

@ -412,7 +412,7 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
int main(int argc, char **argv)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
char *title1 = "gears - main window";
char *title2 = "gears - secondary window";
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL);
@ -433,7 +433,7 @@ int main(int argc, char **argv)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (!sMainWindow) {
printf("could not create main window\n");
exit(-1);
@ -450,7 +450,7 @@ int main(int argc, char **argv)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (!sSecondaryWindow) {
printf("could not create secondary window\n");
exit(-1);

View File

@ -406,13 +406,13 @@ Application::Application(GHOST_ISystem *system)
m_exitRequested(false),
stereo(false)
{
GHOST_GLSettings glSettings = {0};
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
GHOST_GPUSettings gpuSettings = {0};
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
fApp = this;
// Create the main window
m_mainWindow = system->createWindow(
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
if (!m_mainWindow) {
std::cout << "could not create main window\n";
@ -421,7 +421,7 @@ Application::Application(GHOST_ISystem *system)
// Create a secondary window
m_secondaryWindow = system->createWindow(
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
if (!m_secondaryWindow) {
std::cout << "could not create secondary window\n";
exit(-1);

View File

@ -306,7 +306,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
{
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
win = GHOST_CreateWindow(sys,
NULL,
@ -318,7 +318,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
MainWindow *mw = MEM_callocN(sizeof(*mw), "mainwindow_new");
@ -557,7 +557,7 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt)
LoggerWindow *loggerwindow_new(MultiTestApp *app)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
uint32_t screensize[2];
GHOST_WindowHandle win;
@ -573,7 +573,7 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
LoggerWindow *lw = MEM_callocN(sizeof(*lw), "loggerwindow_new");
@ -761,7 +761,7 @@ static void extrawindow_handle(void *priv, GHOST_EventHandle evt)
ExtraWindow *extrawindow_new(MultiTestApp *app)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
@ -775,7 +775,7 @@ ExtraWindow *extrawindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
ExtraWindow *ew = MEM_callocN(sizeof(*ew), "mainwindow_new");

View File

@ -335,6 +335,7 @@ compositor_node_categories = [
NodeItem("CompositorNodeSunBeams"),
NodeItem("CompositorNodeDenoise"),
NodeItem("CompositorNodeAntiAliasing"),
NodeItem("CompositorNodeKuwahara"),
]),
CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[
NodeItem("CompositorNodeNormal"),

View File

@ -1061,6 +1061,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_INPAINT 272
#define CMP_NODE_DESPECKLE 273
#define CMP_NODE_ANTIALIASING 274
#define CMP_NODE_KUWAHARA 275
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302

View File

@ -669,7 +669,7 @@ static void autotrack_context_step_cb(void *__restrict userdata,
&libmv_reference_marker);
}
else {
BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOS_FRAME);
BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOUS_FRAME);
autotrack_result->libmv_marker.reference_frame = libmv_current_marker->frame;
libmv_reference_marker = *libmv_current_marker;
}

View File

@ -322,6 +322,8 @@ if(WITH_COMPOSITOR_CPU)
nodes/COM_FilterNode.h
nodes/COM_InpaintNode.cc
nodes/COM_InpaintNode.h
nodes/COM_KuwaharaNode.h
nodes/COM_KuwaharaNode.cc
nodes/COM_PosterizeNode.cc
nodes/COM_PosterizeNode.h
@ -349,6 +351,10 @@ if(WITH_COMPOSITOR_CPU)
operations/COM_GaussianXBlurOperation.h
operations/COM_GaussianYBlurOperation.cc
operations/COM_GaussianYBlurOperation.h
operations/COM_KuwaharaClassicOperation.h
operations/COM_KuwaharaClassicOperation.cc
operations/COM_KuwaharaAnisotropicOperation.h
operations/COM_KuwaharaAnisotropicOperation.cc
operations/COM_MovieClipAttributeOperation.cc
operations/COM_MovieClipAttributeOperation.h
operations/COM_MovieDistortionOperation.cc

View File

@ -62,6 +62,7 @@
#include "COM_InvertNode.h"
#include "COM_KeyingNode.h"
#include "COM_KeyingScreenNode.h"
#include "COM_KuwaharaNode.h"
#include "COM_LensDistortionNode.h"
#include "COM_LuminanceMatteNode.h"
#include "COM_MapRangeNode.h"
@ -436,6 +437,9 @@ Node *COM_convert_bnode(bNode *b_node)
case CMP_NODE_COMBINE_XYZ:
node = new CombineXYZNode(b_node);
break;
case CMP_NODE_KUWAHARA:
node = new KuwaharaNode(b_node);
break;
}
return node;
}

View File

@ -0,0 +1,103 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "COM_KuwaharaNode.h"
#include "COM_FastGaussianBlurOperation.h"
#include "COM_KuwaharaAnisotropicOperation.h"
#include "COM_KuwaharaClassicOperation.h"
#include "COM_MathBaseOperation.h"
#include "COM_SetValueOperation.h"
namespace blender::compositor {
void KuwaharaNode::convert_to_operations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
const bNode *node = this->get_bnode();
const NodeKuwaharaData *data = (const NodeKuwaharaData *)node->storage;
switch (data->variation) {
case CMP_NODE_KUWAHARA_CLASSIC: {
KuwaharaClassicOperation *operation = new KuwaharaClassicOperation();
operation->set_kernel_size(data->size);
converter.add_operation(operation);
converter.map_input_socket(get_input_socket(0), operation->get_input_socket(0));
converter.map_output_socket(get_output_socket(0), operation->get_output_socket());
break;
}
case CMP_NODE_KUWAHARA_ANISOTROPIC: {
/* Edge detection */
auto const_fact = new SetValueOperation();
const_fact->set_value(1.0f);
converter.add_operation(const_fact);
auto sobel_x = new ConvolutionFilterOperation();
sobel_x->set3x3Filter(1, 0, -1, 2, 0, -2, 1, 0, -1);
converter.add_operation(sobel_x);
converter.map_input_socket(get_input_socket(0), sobel_x->get_input_socket(0));
converter.add_link(const_fact->get_output_socket(0), sobel_x->get_input_socket(1));
auto sobel_y = new ConvolutionFilterOperation();
sobel_y->set3x3Filter(1, 2, 1, 0, 0, 0, -1, -2, -1);
converter.add_operation(sobel_y);
converter.map_input_socket(get_input_socket(0), sobel_y->get_input_socket(0));
converter.add_link(const_fact->get_output_socket(0), sobel_y->get_input_socket(1));
/* Compute intensity of edges */
auto sobel_xx = new MathMultiplyOperation();
auto sobel_yy = new MathMultiplyOperation();
auto sobel_xy = new MathMultiplyOperation();
converter.add_operation(sobel_xx);
converter.add_operation(sobel_yy);
converter.add_operation(sobel_xy);
converter.add_link(sobel_x->get_output_socket(0), sobel_xx->get_input_socket(0));
converter.add_link(sobel_x->get_output_socket(0), sobel_xx->get_input_socket(1));
converter.add_link(sobel_y->get_output_socket(0), sobel_yy->get_input_socket(0));
converter.add_link(sobel_y->get_output_socket(0), sobel_yy->get_input_socket(1));
converter.add_link(sobel_x->get_output_socket(0), sobel_xy->get_input_socket(0));
converter.add_link(sobel_y->get_output_socket(0), sobel_xy->get_input_socket(1));
/* Blurring for more robustness. */
const int sigma = data->smoothing;
auto blur_sobel_xx = new FastGaussianBlurOperation();
auto blur_sobel_yy = new FastGaussianBlurOperation();
auto blur_sobel_xy = new FastGaussianBlurOperation();
blur_sobel_yy->set_size(sigma, sigma);
blur_sobel_xx->set_size(sigma, sigma);
blur_sobel_xy->set_size(sigma, sigma);
converter.add_operation(blur_sobel_xx);
converter.add_operation(blur_sobel_yy);
converter.add_operation(blur_sobel_xy);
converter.add_link(sobel_xx->get_output_socket(0), blur_sobel_xx->get_input_socket(0));
converter.add_link(sobel_yy->get_output_socket(0), blur_sobel_yy->get_input_socket(0));
converter.add_link(sobel_xy->get_output_socket(0), blur_sobel_xy->get_input_socket(0));
/* Apply anisotropic Kuwahara filter. */
KuwaharaAnisotropicOperation *aniso = new KuwaharaAnisotropicOperation();
aniso->set_kernel_size(data->size + 4);
converter.map_input_socket(get_input_socket(0), aniso->get_input_socket(0));
converter.add_operation(aniso);
converter.add_link(blur_sobel_xx->get_output_socket(0), aniso->get_input_socket(1));
converter.add_link(blur_sobel_yy->get_output_socket(0), aniso->get_input_socket(2));
converter.add_link(blur_sobel_xy->get_output_socket(0), aniso->get_input_socket(3));
converter.map_output_socket(get_output_socket(0), aniso->get_output_socket(0));
break;
}
}
}
} // namespace blender::compositor

View File

@ -0,0 +1,23 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "COM_Node.h"
namespace blender::compositor {
/**
* \brief KuwaharaNode
* \ingroup Node
*/
class KuwaharaNode : public Node {
public:
KuwaharaNode(bNode *editor_node) : Node(editor_node) {}
void convert_to_operations(NodeConverter &converter,
const CompositorContext &context) const override;
};
} // namespace blender::compositor

View File

@ -11,6 +11,7 @@ namespace blender::compositor {
FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation(DataType::Color)
{
iirgaus_ = nullptr;
data_.filtertype = R_FILTER_FAST_GAUSS;
}
void FastGaussianBlurOperation::execute_pixel(float output[4], int x, int y, void *data)
@ -68,6 +69,15 @@ void FastGaussianBlurOperation::deinit_execution()
BlurBaseOperation::deinit_mutex();
}
void FastGaussianBlurOperation::set_size(int size_x, int size_y)
{
/* TODO: there should be a better way to use the operation without knowing specifics of the blur
* node (i.e. data_). We could use factory pattern to solve this problem. */
data_.sizex = size_x;
data_.sizey = size_y;
sizeavailable_ = true;
}
void *FastGaussianBlurOperation::initialize_tile_data(rcti *rect)
{
lock_mutex();

View File

@ -28,6 +28,8 @@ class FastGaussianBlurOperation : public BlurBaseOperation {
void deinit_execution() override;
void init_execution() override;
void set_size(int size_x, int size_y);
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_started(MemoryBuffer *output,
const rcti &area,

View File

@ -0,0 +1,295 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "COM_KuwaharaAnisotropicOperation.h"
#include "BLI_math_base.hh"
#include "BLI_vector.hh"
#include "IMB_colormanagement.h"
namespace blender::compositor {
KuwaharaAnisotropicOperation::KuwaharaAnisotropicOperation()
{
this->add_input_socket(DataType::Color);
this->add_input_socket(DataType::Color);
this->add_input_socket(DataType::Color);
this->add_input_socket(DataType::Color);
this->add_output_socket(DataType::Color);
this->n_div_ = 8;
this->set_kernel_size(5);
this->flags_.is_fullframe_operation = true;
}
void KuwaharaAnisotropicOperation::init_execution()
{
image_reader_ = this->get_input_socket_reader(0);
s_xx_reader_ = this->get_input_socket_reader(1);
s_yy_reader_ = this->get_input_socket_reader(2);
s_xy_reader_ = this->get_input_socket_reader(3);
}
void KuwaharaAnisotropicOperation::deinit_execution()
{
image_reader_ = nullptr;
}
void KuwaharaAnisotropicOperation::execute_pixel_sampled(float output[4],
float x,
float y,
PixelSampler sampler)
{
const int width = this->get_width();
const int height = this->get_height();
BLI_assert(width == s_xx_reader_->get_width());
BLI_assert(height == s_xx_reader_->get_height());
BLI_assert(width == s_yy_reader_->get_width());
BLI_assert(height == s_yy_reader_->get_height());
BLI_assert(width == s_xy_reader_->get_width());
BLI_assert(height == s_xy_reader_->get_height());
/* Values recommended by authors in original paper. */
const float angle = 2.0 * M_PI / n_div_;
const float q = 3.0;
const float EPS = 1.0e-10;
/* For now use green channel to compute orientation. */
/* TODO: convert to HSV and compute orientation and strength on luminance channel */
float tmp[4];
s_xx_reader_->read(tmp, x, y, nullptr);
const float a = tmp[1];
s_xy_reader_->read(tmp, x, y, nullptr);
const float b = tmp[1];
s_yy_reader_->read(tmp, x, y, nullptr);
const float c = tmp[1];
/* Compute egenvalues of structure tensor. */
const double tr = a + c;
const double discr = sqrt((a - b) * (a - b) + 4 * b * c);
const double lambda1 = (tr + discr) / 2;
const double lambda2 = (tr - discr) / 2;
/* Compute orientation and its strength based on structure tensor. */
const double orientation = 0.5 * atan2(2 * b, a - c);
const double strength = (lambda1 == 0 && lambda2 == 0) ?
0 :
(lambda1 - lambda2) / (lambda1 + lambda2);
Vector<double> mean(n_div_);
Vector<double> sum(n_div_);
Vector<double> var(n_div_);
Vector<double> weight(n_div_);
for (int ch = 0; ch < 3; ch++) {
mean.fill(0.0);
sum.fill(0.0);
var.fill(0.0);
weight.fill(0.0);
double sx = 1.0f / (strength + 1.0f);
double sy = (1.0f + strength) / 1.0f;
double theta = -orientation;
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
if (dx == 0 && dy == 0)
continue;
/* Rotate and scale the kernel. This is the "anisotropic" part. */
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
/* Clamp image to avoid artefacts at borders. */
const int xx = math::clamp(int(x) + dx2, 0, width - 1);
const int yy = math::clamp(int(y) + dy2, 0, height - 1);
const double ddx2 = double(dx2);
const double ddy2 = double(dy2);
const double theta = atan2(ddy2, ddx2) + M_PI;
const int t = int(floor(theta / angle)) % n_div_;
double d2 = dx2 * dx2 + dy2 * dy2;
double g = exp(-d2 / (2.0 * kernel_size_));
float color[4];
image_reader_->read(color, xx, yy, nullptr);
const double v = color[ch];
/* todo(zazizizou): only compute lum once per region */
const float lum = IMB_colormanagement_get_luminance(color);
/* todo(zazizizou): only compute mean for the selected region */
mean[t] += g * v;
sum[t] += g * lum;
var[t] += g * lum * lum;
weight[t] += g;
}
}
/* Calculate weighted average */
double de = 0.0;
double nu = 0.0;
for (int i = 0; i < n_div_; i++) {
double weight_inv = 1.0 / weight[i];
mean[i] = weight[i] != 0 ? mean[i] * weight_inv : 0.0;
sum[i] = weight[i] != 0 ? sum[i] * weight_inv : 0.0;
var[i] = weight[i] != 0 ? var[i] * weight_inv : 0.0;
var[i] = var[i] - sum[i] * sum[i];
var[i] = var[i] > FLT_EPSILON ? sqrt(var[i]) : FLT_EPSILON;
double w = powf(var[i], -q);
de += mean[i] * w;
nu += w;
}
double val = nu > EPS ? de / nu : 0.0;
output[ch] = val;
}
/* No changes for alpha channel. */
image_reader_->read_sampled(tmp, x, y, sampler);
output[3] = tmp[3];
}
void KuwaharaAnisotropicOperation::set_kernel_size(int kernel_size)
{
/* Filter will be split into n_div.
* Add n_div / 2 to avoid artefacts such as random black pixels in image. */
kernel_size_ = kernel_size + n_div_ / 2;
}
int KuwaharaAnisotropicOperation::get_kernel_size()
{
return kernel_size_;
}
int KuwaharaAnisotropicOperation::get_n_div()
{
return n_div_;
}
void KuwaharaAnisotropicOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
/* Implementation based on Kyprianidis, Jan & Kang, Henry & Döllner, Jürgen. (2009).
* "Image and Video Abstraction by Anisotropic Kuwahara Filtering".
* Comput. Graph. Forum. 28. 1955-1963. 10.1111/j.1467-8659.2009.01574.x.
* Used reference implementation from lime image processing library (MIT license). */
MemoryBuffer *image = inputs[0];
MemoryBuffer *s_xx = inputs[1];
MemoryBuffer *s_yy = inputs[2];
MemoryBuffer *s_xy = inputs[3];
const int width = image->get_width();
const int height = image->get_height();
BLI_assert(width == s_xx->get_width());
BLI_assert(height == s_xx->get_height());
BLI_assert(width == s_yy->get_width());
BLI_assert(height == s_yy->get_height());
BLI_assert(width == s_xy->get_width());
BLI_assert(height == s_xy->get_height());
/* Values recommended by authors in original paper. */
const float angle = 2.0 * M_PI / n_div_;
const float q = 3.0;
const float EPS = 1.0e-10;
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const int x = it.x;
const int y = it.y;
/* For now use green channel to compute orientation. */
/* TODO: convert to HSV and compute orientation and strength on luminance channel. */
const float a = s_xx->get_value(x, y, 1);
const float b = s_xy->get_value(x, y, 1);
const float c = s_yy->get_value(x, y, 1);
/* Compute egenvalues of structure tensor */
const double tr = a + c;
const double discr = sqrt((a - b) * (a - b) + 4 * b * c);
const double lambda1 = (tr + discr) / 2;
const double lambda2 = (tr - discr) / 2;
/* Compute orientation and its strength based on structure tensor. */
const double orientation = 0.5 * atan2(2 * b, a - c);
const double strength = (lambda1 == 0 && lambda2 == 0) ?
0 :
(lambda1 - lambda2) / (lambda1 + lambda2);
Vector<double> mean(n_div_);
Vector<double> sum(n_div_);
Vector<double> var(n_div_);
Vector<double> weight(n_div_);
for (int ch = 0; ch < 3; ch++) {
mean.fill(0.0);
sum.fill(0.0);
var.fill(0.0);
weight.fill(0.0);
double sx = 1.0f / (strength + 1.0f);
double sy = (1.0f + strength) / 1.0f;
double theta = -orientation;
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
if (dx == 0 && dy == 0)
continue;
/* Rotate and scale the kernel. This is the "anisotropic" part. */
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
/* Clamp image to avoid artefacts at borders. */
const int xx = math::clamp(x + dx2, 0, width - 1);
const int yy = math::clamp(y + dy2, 0, height - 1);
const double ddx2 = double(dx2);
const double ddy2 = double(dy2);
const double theta = atan2(ddy2, ddx2) + M_PI;
const int t = int(floor(theta / angle)) % n_div_;
double d2 = dx2 * dx2 + dy2 * dy2;
double g = exp(-d2 / (2.0 * kernel_size_));
const double v = image->get_value(xx, yy, ch);
float color[4];
image->read_elem(xx, yy, color);
/* TODO(zazizizou): only compute lum once per region. */
const float lum = IMB_colormanagement_get_luminance(color);
/* TODO(zazizizou): only compute mean for the selected region. */
mean[t] += g * v;
sum[t] += g * lum;
var[t] += g * lum * lum;
weight[t] += g;
}
}
/* Calculate weighted average. */
double de = 0.0;
double nu = 0.0;
for (int i = 0; i < n_div_; i++) {
double weight_inv = 1.0 / weight[i];
mean[i] = weight[i] != 0 ? mean[i] * weight_inv : 0.0;
sum[i] = weight[i] != 0 ? sum[i] * weight_inv : 0.0;
var[i] = weight[i] != 0 ? var[i] * weight_inv : 0.0;
var[i] = var[i] - sum[i] * sum[i];
var[i] = var[i] > FLT_EPSILON ? sqrt(var[i]) : FLT_EPSILON;
double w = powf(var[i], -q);
de += mean[i] * w;
nu += w;
}
double val = nu > EPS ? de / nu : 0.0;
it.out[ch] = val;
}
/* No changes for alpha channel. */
it.out[3] = image->get_value(x, y, 3);
}
}
} // namespace blender::compositor

View File

@ -0,0 +1,36 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
class KuwaharaAnisotropicOperation : public MultiThreadedOperation {
SocketReader *image_reader_;
SocketReader *s_xx_reader_;
SocketReader *s_yy_reader_;
SocketReader *s_xy_reader_;
int kernel_size_;
int n_div_;
public:
KuwaharaAnisotropicOperation();
void init_execution() override;
void deinit_execution() override;
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
void set_kernel_size(int kernel_size);
int get_kernel_size();
int get_n_div();
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@ -0,0 +1,199 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "COM_KuwaharaClassicOperation.h"
#include "IMB_colormanagement.h"
namespace blender::compositor {
KuwaharaClassicOperation::KuwaharaClassicOperation()
{
this->add_input_socket(DataType::Color);
this->add_output_socket(DataType::Color);
this->set_kernel_size(4);
this->flags_.is_fullframe_operation = true;
}
void KuwaharaClassicOperation::init_execution()
{
image_reader_ = this->get_input_socket_reader(0);
}
void KuwaharaClassicOperation::deinit_execution()
{
image_reader_ = nullptr;
}
void KuwaharaClassicOperation::execute_pixel_sampled(float output[4],
float x,
float y,
PixelSampler sampler)
{
for (int ch = 0; ch < 3; ch++) {
float sum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float mean[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float var[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int cnt[4] = {0, 0, 0, 0};
/* Split surroundings of pixel into 4 overlapping regions. */
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
int xx = x + dx;
int yy = y + dy;
if (xx >= 0 && yy >= 0 && xx < this->get_width() && yy < this->get_height()) {
float color[4];
image_reader_->read_sampled(color, xx, yy, sampler);
const float v = color[ch];
const float lum = IMB_colormanagement_get_luminance(color);
if (dx <= 0 && dy <= 0) {
mean[0] += v;
sum[0] += lum;
var[0] += lum * lum;
cnt[0]++;
}
if (dx >= 0 && dy <= 0) {
mean[1] += v;
sum[1] += lum;
var[1] += lum * lum;
cnt[1]++;
}
if (dx <= 0 && dy >= 0) {
mean[2] += v;
sum[2] += lum;
var[2] += lum * lum;
cnt[2]++;
}
if (dx >= 0 && dy >= 0) {
mean[3] += v;
sum[3] += lum;
var[3] += lum * lum;
cnt[3]++;
}
}
}
}
/* Compute region variances. */
for (int i = 0; i < 4; i++) {
mean[i] = cnt[i] != 0 ? mean[i] / cnt[i] : 0.0f;
sum[i] = cnt[i] != 0 ? sum[i] / cnt[i] : 0.0f;
var[i] = cnt[i] != 0 ? var[i] / cnt[i] : 0.0f;
const float temp = sum[i] * sum[i];
var[i] = var[i] > temp ? sqrt(var[i] - temp) : 0.0f;
}
/* Choose the region with lowest variance. */
float min_var = FLT_MAX;
int min_index = 0;
for (int i = 0; i < 4; i++) {
if (var[i] < min_var) {
min_var = var[i];
min_index = i;
}
}
output[ch] = mean[min_index];
}
}
void KuwaharaClassicOperation::set_kernel_size(int kernel_size)
{
kernel_size_ = kernel_size;
}
int KuwaharaClassicOperation::get_kernel_size()
{
return kernel_size_;
}
void KuwaharaClassicOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
MemoryBuffer *image = inputs[0];
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const int x = it.x;
const int y = it.y;
it.out[3] = image->get_value(x, y, 3);
for (int ch = 0; ch < 3; ch++) {
float sum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float mean[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float var[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int cnt[4] = {0, 0, 0, 0};
/* Split surroundings of pixel into 4 overlapping regions. */
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
int xx = x + dx;
int yy = y + dy;
if (xx >= 0 && yy >= 0 && xx < image->get_width() && yy < image->get_height()) {
const float v = image->get_value(xx, yy, ch);
float color[4];
image->read_elem(xx, yy, color);
const float lum = IMB_colormanagement_get_luminance(color);
if (dx <= 0 && dy <= 0) {
mean[0] += v;
sum[0] += lum;
var[0] += lum * lum;
cnt[0]++;
}
if (dx >= 0 && dy <= 0) {
mean[1] += v;
sum[1] += lum;
var[1] += lum * lum;
cnt[1]++;
}
if (dx <= 0 && dy >= 0) {
mean[2] += v;
sum[2] += lum;
var[2] += lum * lum;
cnt[2]++;
}
if (dx >= 0 && dy >= 0) {
mean[3] += v;
sum[3] += lum;
var[3] += lum * lum;
cnt[3]++;
}
}
}
}
/* Compute region variances. */
for (int i = 0; i < 4; i++) {
mean[i] = cnt[i] != 0 ? mean[i] / cnt[i] : 0.0f;
sum[i] = cnt[i] != 0 ? sum[i] / cnt[i] : 0.0f;
var[i] = cnt[i] != 0 ? var[i] / cnt[i] : 0.0f;
const float temp = sum[i] * sum[i];
var[i] = var[i] > temp ? sqrt(var[i] - temp) : 0.0f;
}
/* Choose the region with lowest variance. */
float min_var = FLT_MAX;
int min_index = 0;
for (int i = 0; i < 4; i++) {
if (var[i] < min_var) {
min_var = var[i];
min_index = i;
}
}
output->get_value(x, y, ch) = mean[min_index];
}
}
}
} // namespace blender::compositor

View File

@ -0,0 +1,31 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
class KuwaharaClassicOperation : public MultiThreadedOperation {
SocketReader *image_reader_;
int kernel_size_;
public:
KuwaharaClassicOperation();
void init_execution() override;
void deinit_execution() override;
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
void set_kernel_size(int kernel_size);
int get_kernel_size();
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@ -152,6 +152,7 @@ set(GLSL_SRC
shaders/compositor_smaa_edge_detection.glsl
shaders/compositor_smaa_neighborhood_blending.glsl
shaders/compositor_split_viewer.glsl
shaders/compositor_sun_beams.glsl
shaders/compositor_symmetric_blur.glsl
shaders/compositor_symmetric_blur_variable_size.glsl
shaders/compositor_symmetric_separable_blur.glsl
@ -252,6 +253,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/infos/compositor_screen_lens_distortion_info.hh
shaders/infos/compositor_smaa_info.hh
shaders/infos/compositor_split_viewer_info.hh
shaders/infos/compositor_sun_beams_info.hh
shaders/infos/compositor_symmetric_blur_info.hh
shaders/infos/compositor_symmetric_blur_variable_size_info.hh
shaders/infos/compositor_symmetric_separable_blur_info.hh

View File

@ -0,0 +1,32 @@
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
ivec2 input_size = texture_size(input_tx);
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(input_size);
vec2 vector_to_source = source - coordinates;
float distance_to_source = length(vector_to_source);
vec2 direction_to_source = vector_to_source / distance_to_source;
/* We integrate from the current pixel to the source pixel, but up until the user specified
* maximum ray length. The number of integration steps is roughly equivalent to the number of
* pixels along the integration path. Assume a minimum number of steps of 1 to avoid zero
* division handling and return source pixels as is. */
float integration_length = min(distance_to_source, max_ray_length);
float integration_length_in_pixels = length(input_size) * integration_length;
int steps = max(1, int(integration_length_in_pixels));
vec2 step_vector = (direction_to_source * integration_length) / steps;
vec4 accumulated_color = vec4(0.0);
for (int i = 0; i < steps; i++) {
/* Attenuate the contributions of pixels that are further away from the source using a
* quadratic falloff. */
float weight = pow(1.0f - i / integration_length_in_pixels, 2.0);
accumulated_color += texture(input_tx, coordinates + i * step_vector) * weight;
}
imageStore(output_img, texel, accumulated_color / steps);
}

View File

@ -0,0 +1,14 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(compositor_sun_beams)
.local_group_size(16, 16)
.push_constant(Type::VEC2, "source")
.push_constant(Type::FLOAT, "max_ray_length")
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.compute_source("compositor_sun_beams.glsl")
.do_static_compilation(true);

View File

@ -162,15 +162,15 @@ void DRW_uniform_attrs_pool_free(struct GHash *table);
void DRW_render_context_enable(struct Render *render);
void DRW_render_context_disable(struct Render *render);
void DRW_opengl_context_create(void);
void DRW_opengl_context_destroy(void);
void DRW_opengl_context_enable(void);
void DRW_opengl_context_disable(void);
void DRW_gpu_context_create(void);
void DRW_gpu_context_destroy(void);
void DRW_gpu_context_enable(void);
void DRW_gpu_context_disable(void);
#ifdef WITH_XR_OPENXR
/* XXX: see comment on #DRW_xr_opengl_context_get() */
void *DRW_xr_opengl_context_get(void);
void *DRW_xr_gpu_context_get(void);
/* XXX: see comment on #DRW_system_gpu_context_get() */
void *DRW_system_gpu_context_get(void);
void *DRW_xr_blender_gpu_context_get(void);
void DRW_xr_drawing_begin(void);
void DRW_xr_drawing_end(void);
#endif
@ -183,19 +183,16 @@ void DRW_cache_free_old_subdiv(void);
void DRW_subdiv_free(void);
/* Never use this. Only for closing blender. */
void DRW_opengl_context_enable_ex(bool restore);
void DRW_opengl_context_disable_ex(bool restore);
void DRW_gpu_context_enable_ex(bool restore);
void DRW_gpu_context_disable_ex(bool restore);
void DRW_opengl_render_context_enable(void *re_gl_context);
void DRW_opengl_render_context_disable(void *re_gl_context);
/**
* Needs to be called AFTER #DRW_opengl_render_context_enable().
*/
void DRW_gpu_render_context_enable(void *re_gpu_context);
/**
* Needs to be called BEFORE #DRW_opengl_render_context_disable().
*/
void DRW_gpu_render_context_disable(void *re_gpu_context);
/* Render pipeline GPU context control.
* Enable system context first, then enable blender context,
* then disable blender context, then disable system context. */
void DRW_system_gpu_render_context_enable(void *re_system_gpu_context);
void DRW_system_gpu_render_context_disable(void *re_system_gpu_context);
void DRW_blender_gpu_render_context_enable(void *re_gpu_context);
void DRW_blender_gpu_render_context_disable(void *re_gpu_context);
void DRW_deferred_shader_remove(struct GPUMaterial *mat);
void DRW_deferred_shader_optimize_remove(struct GPUMaterial *mat);
@ -210,8 +207,8 @@ void DRW_drawdata_free(struct ID *id);
struct DRWData *DRW_viewport_data_create(void);
void DRW_viewport_data_free(struct DRWData *drw_data);
bool DRW_opengl_context_release(void);
void DRW_opengl_context_activate(bool drw_state);
bool DRW_gpu_context_release(void);
void DRW_gpu_context_activate(bool drw_state);
/**
* We may want to move this into a more general location.

View File

@ -62,13 +62,13 @@
(IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y)
/* TODO: should be replace by a more elegant alternative. */
extern void DRW_opengl_context_enable(void);
extern void DRW_opengl_context_disable(void);
extern void DRW_gpu_context_enable(void);
extern void DRW_gpu_context_disable(void);
extern void DRW_opengl_render_context_enable(void *re_gl_context);
extern void DRW_opengl_render_context_disable(void *re_gl_context);
extern void DRW_gpu_render_context_enable(void *re_gpu_context);
extern void DRW_gpu_render_context_disable(void *re_gpu_context);
extern void DRW_system_gpu_render_context_enable(void *re_system_gpu_context);
extern void DRW_system_gpu_render_context_disable(void *re_system_gpu_context);
extern void DRW_blender_gpu_render_context_enable(void *re_blender_gpu_context);
extern void DRW_blender_gpu_render_context_disable(void *re_blender_gpu_context);
typedef struct EEVEE_LightBake {
Depsgraph *depsgraph;
@ -157,7 +157,7 @@ typedef struct EEVEE_LightBake {
int frame;
/** If running in parallel (in a separate thread), use this context. */
void *gl_context, *gpu_context;
void *system_gpu_context, *blender_gpu_context;
ThreadMutex *mutex;
} EEVEE_LightBake;
@ -601,20 +601,20 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
{
if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
GPU_context_main_lock();
DRW_opengl_context_enable();
DRW_gpu_context_enable();
GPU_render_begin();
return;
}
if (lbake->gl_context) {
DRW_opengl_render_context_enable(lbake->gl_context);
if (lbake->gpu_context == NULL) {
lbake->gpu_context = GPU_context_create(NULL, lbake->gl_context);
if (lbake->system_gpu_context) {
DRW_system_gpu_render_context_enable(lbake->system_gpu_context);
if (lbake->blender_gpu_context == NULL) {
lbake->blender_gpu_context = GPU_context_create(NULL, lbake->system_gpu_context);
}
DRW_gpu_render_context_enable(lbake->gpu_context);
DRW_blender_gpu_render_context_enable(lbake->blender_gpu_context);
}
else {
DRW_opengl_context_enable();
DRW_gpu_context_enable();
}
GPU_render_begin();
}
@ -623,19 +623,19 @@ static void eevee_lightbake_context_disable(EEVEE_LightBake *lbake)
{
if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
DRW_opengl_context_disable();
DRW_gpu_context_disable();
GPU_render_end();
GPU_context_main_unlock();
return;
}
if (lbake->gl_context) {
DRW_gpu_render_context_disable(lbake->gpu_context);
if (lbake->system_gpu_context) {
DRW_blender_gpu_render_context_disable(lbake->blender_gpu_context);
GPU_render_end();
DRW_opengl_render_context_disable(lbake->gl_context);
DRW_system_gpu_render_context_disable(lbake->system_gpu_context);
}
else {
DRW_opengl_context_disable();
DRW_gpu_context_disable();
GPU_render_end();
}
}
@ -788,13 +788,13 @@ wmJob *EEVEE_lightbake_job_create(wmWindowManager *wm,
lbake->scene = scene;
lbake->bmain = bmain;
lbake->view_layer_input = view_layer;
lbake->gl_context = old_lbake->gl_context;
lbake->system_gpu_context = old_lbake->system_gpu_context;
lbake->own_resources = true;
lbake->delay = delay;
lbake->frame = frame;
if (lbake->gl_context == NULL && !GPU_use_main_context_workaround()) {
lbake->gl_context = WM_opengl_context_create();
if (lbake->system_gpu_context == NULL && !GPU_use_main_context_workaround()) {
lbake->system_gpu_context = WM_system_gpu_context_create();
wm_window_reset_drawable();
}
@ -835,7 +835,7 @@ void *EEVEE_lightbake_job_data_alloc(
lbake->frame = frame;
if (run_as_job && !GPU_use_main_context_workaround()) {
lbake->gl_context = WM_opengl_context_create();
lbake->system_gpu_context = WM_system_gpu_context_create();
wm_window_reset_drawable();
}
@ -865,12 +865,12 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
BLI_mutex_lock(lbake->mutex);
}
if (lbake->gl_context) {
DRW_opengl_render_context_enable(lbake->gl_context);
DRW_gpu_render_context_enable(lbake->gpu_context);
if (lbake->system_gpu_context) {
DRW_system_gpu_render_context_enable(lbake->system_gpu_context);
DRW_blender_gpu_render_context_enable(lbake->blender_gpu_context);
}
else if (!lbake->resource_only) {
DRW_opengl_context_enable();
DRW_gpu_context_enable();
}
/* XXX: Free the resources contained in the view-layer data
@ -887,24 +887,24 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
GPU_FRAMEBUFFER_FREE_SAFE(lbake->rt_fb[i]);
}
if (lbake->gpu_context) {
DRW_gpu_render_context_disable(lbake->gpu_context);
DRW_gpu_render_context_enable(lbake->gpu_context);
GPU_context_discard(lbake->gpu_context);
if (lbake->blender_gpu_context) {
DRW_blender_gpu_render_context_disable(lbake->blender_gpu_context);
DRW_blender_gpu_render_context_enable(lbake->blender_gpu_context);
GPU_context_discard(lbake->blender_gpu_context);
}
if (lbake->gl_context && lbake->own_resources) {
if (lbake->system_gpu_context && lbake->own_resources) {
/* Delete the baking context. */
DRW_opengl_render_context_disable(lbake->gl_context);
WM_opengl_context_dispose(lbake->gl_context);
lbake->gpu_context = NULL;
lbake->gl_context = NULL;
DRW_system_gpu_render_context_disable(lbake->system_gpu_context);
WM_system_gpu_context_dispose(lbake->system_gpu_context);
lbake->blender_gpu_context = NULL;
lbake->system_gpu_context = NULL;
}
else if (lbake->gl_context) {
DRW_opengl_render_context_disable(lbake->gl_context);
else if (lbake->system_gpu_context) {
DRW_system_gpu_render_context_disable(lbake->system_gpu_context);
}
else if (!lbake->resource_only) {
DRW_opengl_context_disable();
DRW_gpu_context_disable();
}
if (!lbake->resource_only) {
@ -1490,10 +1490,10 @@ void EEVEE_lightbake_job(void *custom_data, bool *stop, bool *do_update, float *
lcache->flag |= LIGHTCACHE_BAKED;
lcache->flag &= ~LIGHTCACHE_BAKING;
/* Assume that if lbake->gl_context is NULL
/* Assume that if lbake->system_gpu_context is NULL
* we are not running in this in a job, so update
* the scene light-cache pointer before deleting it. */
if (lbake->gl_context == NULL) {
if (lbake->system_gpu_context == NULL) {
BLI_assert(BLI_thread_is_main());
EEVEE_lightbake_update(lbake);
}

View File

@ -710,7 +710,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
/* If light-cache auto-update is enable we tag the relevant part
* of the cache to update and fire up a baking job. */
if (!DRW_state_is_image_render() && !DRW_state_is_opengl_render() &&
if (!DRW_state_is_image_render() && !DRW_state_is_viewport_image_render() &&
(pinfo->do_grid_update || pinfo->do_cube_update))
{
BLI_assert(draw_ctx->evil_C);

View File

@ -94,7 +94,7 @@ void EEVEE_lookdev_init(EEVEE_Data *vedata)
/* Viewport / Spheres size. */
const rcti *rect;
rcti fallback_rect;
if (DRW_state_is_opengl_render()) {
if (DRW_state_is_viewport_image_render()) {
const float *vp_size = DRW_viewport_size_get();
fallback_rect.xmax = vp_size[0];
fallback_rect.ymax = vp_size[1];

View File

@ -431,7 +431,7 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
bool is_valid = (render_pass & EEVEE_RENDERPASSES_ALL) != 0;
bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) != 0 &&
DRW_state_is_opengl_render();
DRW_state_is_viewport_image_render();
UNUSED_VARS(needs_color_transfer);
if ((render_pass & EEVEE_RENDER_PASS_BLOOM) != 0 &&

View File

@ -245,7 +245,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
* Reset for each "redraw". When rendering using OpenGL render,
* we accumulate the redraw inside the drawing loop in eevee_draw_scene().
*/
if (DRW_state_is_opengl_render()) {
if (DRW_state_is_viewport_image_render()) {
effects->taa_render_sample = 1;
}
effects->bypass_drawing = false;

View File

@ -11,6 +11,11 @@ shared float zdists_cache[gl_WorkGroupSize.x];
void main()
{
/* Early exit if no lights are present to prevent out of bounds buffer read. */
if (light_cull_buf.visible_count == 0) {
return;
}
uint src_index = gl_GlobalInvocationID.x;
bool valid_thread = true;

View File

@ -40,7 +40,7 @@ void main()
tile.is_used = true;
}
/* Reset count for next level. */
usage_grid[tile_co.y][tile_co.x] = 0u;
usage_grid[tile_co.y / 2][tile_co.x / 2] = 0u;
}
barrier();

View File

@ -57,7 +57,8 @@ void main()
ivec2 tile_co = ivec2(gl_GlobalInvocationID.xy);
ivec2 tile_shifted = tile_co + tilemap.grid_shift;
ivec2 tile_wrapped = ivec2(tile_shifted % SHADOW_TILEMAP_RES);
/* Ensure value is shifted into positive range to avoid modulo on negative. */
ivec2 tile_wrapped = ivec2((ivec2(SHADOW_TILEMAP_RES) + tile_shifted) % SHADOW_TILEMAP_RES);
/* If this tile was shifted in and contains old information, update it.
* Note that cubemap always shift all tiles on update. */
@ -72,7 +73,7 @@ void main()
uint lod_size = uint(SHADOW_TILEMAP_RES);
for (int lod = 0; lod <= lod_max; lod++, lod_size >>= 1u) {
bool thread_active = all(lessThan(tile_co, ivec2(lod_size)));
ShadowTileDataPacked tile;
ShadowTileDataPacked tile = 0;
int tile_load = shadow_tile_offset(tile_wrapped, tilemap.tiles_index, lod);
if (thread_active) {
tile = init_tile_data(tiles_buf[tile_load], do_update);

View File

@ -30,7 +30,7 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
float color_override[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int background_type;
if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) {
if (DRW_state_is_viewport_image_render() && !DRW_state_draw_background()) {
background_type = BG_SOLID;
color_override[3] = 1.0f;
}

View File

@ -23,7 +23,7 @@ class Background {
float4 color_override(0.0f, 0.0f, 0.0f, 0.0f);
int background_type;
if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) {
if (DRW_state_is_viewport_image_render() && !DRW_state_draw_background()) {
background_type = BG_SOLID;
color_override[3] = 1.0f;
}

View File

@ -630,7 +630,7 @@ static void workbench_draw_scene(void *ved)
WORKBENCH_Data *vedata = ved;
WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
if (DRW_state_is_opengl_render()) {
if (DRW_state_is_viewport_image_render()) {
while (wpd->taa_sample < max_ii(1, wpd->taa_sample_len)) {
workbench_update_world_ubo(wpd);

View File

@ -944,7 +944,7 @@ bool DRW_state_is_scene_render(void);
/**
* Whether we are rendering simple opengl render
*/
bool DRW_state_is_opengl_render(void);
bool DRW_state_is_viewport_image_render(void);
bool DRW_state_is_playback(void);
/**
* Is the user navigating the region.

View File

@ -61,7 +61,7 @@ BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo)
{
/* TODO: do not rely on data uploaded. This prevents multi-threading.
* (need access to a OpenGL context). */
* (need access to a GPU context). */
return (ibo != NULL && !GPU_indexbuf_is_init(ibo));
}

View File

@ -116,7 +116,7 @@ static struct {
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
{
memset(dst, 0x0, offsetof(DRWManager, gl_context));
memset(dst, 0x0, offsetof(DRWManager, system_gpu_context));
}
/* This function is used to reset draw manager to a state
@ -126,7 +126,7 @@ static void drw_state_prepare_clean_for_draw(DRWManager *dst)
#ifdef DEBUG
static void drw_state_ensure_not_reused(DRWManager *dst)
{
memset(dst, 0xff, offsetof(DRWManager, gl_context));
memset(dst, 0xff, offsetof(DRWManager, system_gpu_context));
}
#endif
@ -1341,7 +1341,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
/* XXX Really nasty locking. But else this could
* be executed by the material previews thread
* while rendering a viewport. */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
/* Reset before using it. */
drw_state_prepare_clean_for_draw(&DST);
@ -1378,7 +1378,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
drw_manager_exit(&DST);
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
}
/* update a viewport which belongs to a GPUOffscreen */
@ -1905,7 +1905,7 @@ static void DRW_render_gpencil_to_image(RenderEngine *engine,
void DRW_render_gpencil(RenderEngine *engine, Depsgraph *depsgraph)
{
/* This function should only be called if there are grease pencil objects,
* especially important to avoid failing in background renders without OpenGL context. */
* especially important to avoid failing in background renders without GPU context. */
BLI_assert(DRW_render_check_grease_pencil(depsgraph));
Scene *scene = DEG_get_evaluated_scene(depsgraph);
@ -2964,7 +2964,7 @@ bool DRW_state_is_scene_render(void)
return DST.options.is_scene_render;
}
bool DRW_state_is_opengl_render(void)
bool DRW_state_is_viewport_image_render(void)
{
return DST.options.is_image_render && !DST.options.is_scene_render;
}
@ -3119,14 +3119,14 @@ void DRW_engines_free(void)
{
drw_registered_engines_free();
if (DST.gl_context == NULL) {
if (DST.system_gpu_context == NULL) {
/* Nothing has been setup. Nothing to clear.
* Otherwise, DRW_opengl_context_enable can
* Otherwise, DRW_gpu_context_enable can
* create a context in background mode. (see #62355) */
return;
}
DRW_opengl_context_enable();
DRW_gpu_context_enable();
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
@ -3152,59 +3152,59 @@ void DRW_engines_free(void)
GPU_draw_list_discard(DST.draw_list);
}
DRW_opengl_context_disable();
DRW_gpu_context_disable();
}
void DRW_render_context_enable(Render *render)
{
if (G.background && DST.gl_context == NULL) {
WM_init_opengl();
if (G.background && DST.system_gpu_context == NULL) {
WM_init_gpu();
}
GPU_render_begin();
if (GPU_use_main_context_workaround()) {
GPU_context_main_lock();
DRW_opengl_context_enable();
DRW_gpu_context_enable();
return;
}
void *re_gl_context = RE_gl_context_get(render);
void *re_system_gpu_context = RE_system_gpu_context_get(render);
/* Changing Context */
if (re_gl_context != NULL) {
DRW_opengl_render_context_enable(re_gl_context);
if (re_system_gpu_context != NULL) {
DRW_system_gpu_render_context_enable(re_system_gpu_context);
/* We need to query gpu context after a gl context has been bound. */
void *re_gpu_context = NULL;
re_gpu_context = RE_gpu_context_get(render);
DRW_gpu_render_context_enable(re_gpu_context);
void *re_blender_gpu_context = NULL;
re_blender_gpu_context = RE_blender_gpu_context_get(render);
DRW_blender_gpu_render_context_enable(re_blender_gpu_context);
}
else {
DRW_opengl_context_enable();
DRW_gpu_context_enable();
}
}
void DRW_render_context_disable(Render *render)
{
if (GPU_use_main_context_workaround()) {
DRW_opengl_context_disable();
DRW_gpu_context_disable();
GPU_render_end();
GPU_context_main_unlock();
return;
}
void *re_gl_context = RE_gl_context_get(render);
void *re_system_gpu_context = RE_system_gpu_context_get(render);
if (re_gl_context != NULL) {
void *re_gpu_context = NULL;
re_gpu_context = RE_gpu_context_get(render);
if (re_system_gpu_context != NULL) {
void *re_blender_gpu_context = NULL;
re_blender_gpu_context = RE_blender_gpu_context_get(render);
/* GPU rendering may occur during context disable. */
DRW_gpu_render_context_disable(re_gpu_context);
DRW_blender_gpu_render_context_disable(re_blender_gpu_context);
GPU_render_end();
DRW_opengl_render_context_disable(re_gl_context);
DRW_system_gpu_render_context_disable(re_system_gpu_context);
}
else {
DRW_opengl_context_disable();
DRW_gpu_context_disable();
GPU_render_end();
}
}
@ -3212,51 +3212,51 @@ void DRW_render_context_disable(Render *render)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Init/Exit (DRW_opengl_ctx)
/** \name Init/Exit (DRW_gpu_ctx)
* \{ */
void DRW_opengl_context_create(void)
void DRW_gpu_context_create(void)
{
BLI_assert(DST.gl_context == NULL); /* Ensure it's called once */
BLI_assert(DST.system_gpu_context == NULL); /* Ensure it's called once */
DST.gl_context_mutex = BLI_ticket_mutex_alloc();
DST.system_gpu_context_mutex = BLI_ticket_mutex_alloc();
/* This changes the active context. */
DST.gl_context = WM_opengl_context_create();
WM_opengl_context_activate(DST.gl_context);
/* Be sure to create gpu_context too. */
DST.gpu_context = GPU_context_create(0, DST.gl_context);
DST.system_gpu_context = WM_system_gpu_context_create();
WM_system_gpu_context_activate(DST.system_gpu_context);
/* Be sure to create blender_gpu_context too. */
DST.blender_gpu_context = GPU_context_create(0, DST.system_gpu_context);
/* So we activate the window's one afterwards. */
wm_window_reset_drawable();
}
void DRW_opengl_context_destroy(void)
void DRW_gpu_context_destroy(void)
{
BLI_assert(BLI_thread_is_main());
if (DST.gl_context != NULL) {
WM_opengl_context_activate(DST.gl_context);
GPU_context_active_set(DST.gpu_context);
GPU_context_discard(DST.gpu_context);
WM_opengl_context_dispose(DST.gl_context);
BLI_ticket_mutex_free(DST.gl_context_mutex);
if (DST.system_gpu_context != NULL) {
WM_system_gpu_context_activate(DST.system_gpu_context);
GPU_context_active_set(DST.blender_gpu_context);
GPU_context_discard(DST.blender_gpu_context);
WM_system_gpu_context_dispose(DST.system_gpu_context);
BLI_ticket_mutex_free(DST.system_gpu_context_mutex);
}
}
void DRW_opengl_context_enable_ex(bool UNUSED(restore))
void DRW_gpu_context_enable_ex(bool UNUSED(restore))
{
if (DST.gl_context != NULL) {
if (DST.system_gpu_context != NULL) {
/* IMPORTANT: We don't support immediate mode in render mode!
* This shall remain in effect until immediate mode supports
* multiple threads. */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
GPU_render_begin();
WM_opengl_context_activate(DST.gl_context);
GPU_context_active_set(DST.gpu_context);
WM_system_gpu_context_activate(DST.system_gpu_context);
GPU_context_active_set(DST.blender_gpu_context);
}
}
void DRW_opengl_context_disable_ex(bool restore)
void DRW_gpu_context_disable_ex(bool restore)
{
if (DST.gl_context != NULL) {
if (DST.system_gpu_context != NULL) {
#ifdef __APPLE__
/* Need to flush before disabling draw context, otherwise it does not
* always finish drawing and viewport can be empty or partially drawn */
@ -3269,7 +3269,7 @@ void DRW_opengl_context_disable_ex(bool restore)
wm_window_reset_drawable();
}
else {
WM_opengl_context_release(DST.gl_context);
WM_system_gpu_context_release(DST.system_gpu_context);
GPU_context_active_set(NULL);
}
@ -3277,51 +3277,51 @@ void DRW_opengl_context_disable_ex(bool restore)
* called outside of an existing render loop. */
GPU_render_end();
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
}
}
void DRW_opengl_context_enable(void)
void DRW_gpu_context_enable(void)
{
/* TODO: should be replace by a more elegant alternative. */
if (G.background && DST.gl_context == NULL) {
WM_init_opengl();
if (G.background && DST.system_gpu_context == NULL) {
WM_init_gpu();
}
DRW_opengl_context_enable_ex(true);
DRW_gpu_context_enable_ex(true);
}
void DRW_opengl_context_disable(void)
void DRW_gpu_context_disable(void)
{
DRW_opengl_context_disable_ex(true);
DRW_gpu_context_disable_ex(true);
}
void DRW_opengl_render_context_enable(void *re_gl_context)
void DRW_system_gpu_render_context_enable(void *re_system_gpu_context)
{
/* If thread is main you should use DRW_opengl_context_enable(). */
/* If thread is main you should use DRW_gpu_context_enable(). */
BLI_assert(!BLI_thread_is_main());
/* TODO: get rid of the blocking. Only here because of the static global DST. */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
WM_opengl_context_activate(re_gl_context);
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
WM_system_gpu_context_activate(re_system_gpu_context);
}
void DRW_opengl_render_context_disable(void *re_gl_context)
void DRW_system_gpu_render_context_disable(void *re_system_gpu_context)
{
WM_opengl_context_release(re_gl_context);
WM_system_gpu_context_release(re_system_gpu_context);
/* TODO: get rid of the blocking. */
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
}
void DRW_gpu_render_context_enable(void *re_gpu_context)
void DRW_blender_gpu_render_context_enable(void *re_gpu_context)
{
/* If thread is main you should use DRW_opengl_context_enable(). */
/* If thread is main you should use DRW_gpu_context_enable(). */
BLI_assert(!BLI_thread_is_main());
GPU_context_active_set(re_gpu_context);
}
void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context))
void DRW_blender_gpu_render_context_disable(void *UNUSED(re_gpu_context))
{
GPU_flush();
GPU_context_active_set(NULL);
@ -3331,39 +3331,39 @@ void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context))
#ifdef WITH_XR_OPENXR
void *DRW_xr_opengl_context_get(void)
void *DRW_system_gpu_context_get(void)
{
/* XXX: There should really be no such getter, but for VR we currently can't easily avoid it.
* OpenXR needs some low level info for the OpenGL context that will be used for submitting the
* OpenXR needs some low level info for the GPU context that will be used for submitting the
* final frame-buffer. VR could in theory create its own context, but that would mean we have to
* switch to it just to submit the final frame, which has notable performance impact.
*
* We could "inject" a context through DRW_opengl_render_context_enable(), but that would have to
* work from the main thread, which is tricky to get working too. The preferable solution would
* be using a separate thread for VR drawing where a single context can stay active. */
* We could "inject" a context through DRW_system_gpu_render_context_enable(), but that would
* have to work from the main thread, which is tricky to get working too. The preferable solution
* would be using a separate thread for VR drawing where a single context can stay active. */
return DST.gl_context;
return DST.system_gpu_context;
}
void *DRW_xr_gpu_context_get(void)
void *DRW_xr_blender_gpu_context_get(void)
{
/* XXX: See comment on #DRW_xr_opengl_context_get(). */
/* XXX: See comment on #DRW_system_gpu_context_get(). */
return DST.gpu_context;
return DST.blender_gpu_context;
}
void DRW_xr_drawing_begin(void)
{
/* XXX: See comment on #DRW_xr_opengl_context_get(). */
/* XXX: See comment on #DRW_system_gpu_context_get(). */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
}
void DRW_xr_drawing_end(void)
{
/* XXX: See comment on #DRW_xr_opengl_context_get(). */
/* XXX: See comment on #DRW_system_gpu_context_get(). */
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
}
#endif
@ -3388,58 +3388,59 @@ void DRW_draw_state_init_gtests(eGPUShaderConfig sh_cfg)
/* -------------------------------------------------------------------- */
/** \name Draw manager context release/activation
*
* These functions are used in cases when an OpenGL context creation is needed during the draw.
* This happens, for example, when an external engine needs to create its own OpenGL context from
* These functions are used in cases when an GPU context creation is needed during the draw.
* This happens, for example, when an external engine needs to create its own GPU context from
* the engine initialization.
*
* Example of context creation:
*
* const bool drw_state = DRW_opengl_context_release();
* gl_context = WM_opengl_context_create();
* DRW_opengl_context_activate(drw_state);
* const bool drw_state = DRW_gpu_context_release();
* system_gpu_context = WM_system_gpu_context_create();
* DRW_gpu_context_activate(drw_state);
*
* Example of context destruction:
*
* const bool drw_state = DRW_opengl_context_release();
* WM_opengl_context_activate(gl_context);
* WM_opengl_context_dispose(gl_context);
* DRW_opengl_context_activate(drw_state);
* const bool drw_state = DRW_gpu_context_release();
* WM_system_gpu_context_activate(system_gpu_context);
* WM_system_gpu_context_dispose(system_gpu_context);
* DRW_gpu_context_activate(drw_state);
*
*
* NOTE: Will only perform context modification when on main thread. This way these functions can
* be used in an engine without check on whether it is a draw manager which manages OpenGL context
* on the current thread. The downside of this is that if the engine performs OpenGL creation from
* a non-main thread, that thread is supposed to not have OpenGL context ever bound by Blender.
* be used in an engine without check on whether it is a draw manager which manages GPU context
* on the current thread. The downside of this is that if the engine performs GPU creation from
* a non-main thread, that thread is supposed to not have GPU context ever bound by Blender.
*
* \{ */
bool DRW_opengl_context_release(void)
bool DRW_gpu_context_release(void)
{
if (!BLI_thread_is_main()) {
return false;
}
if (GPU_context_active_get() != DST.gpu_context) {
if (GPU_context_active_get() != DST.blender_gpu_context) {
/* Context release is requested from the outside of the draw manager main draw loop, indicate
* this to the `DRW_opengl_context_activate()` so that it restores drawable of the window. */
* this to the `DRW_gpu_context_activate()` so that it restores drawable of the window.
*/
return false;
}
GPU_context_active_set(NULL);
WM_opengl_context_release(DST.gl_context);
WM_system_gpu_context_release(DST.system_gpu_context);
return true;
}
void DRW_opengl_context_activate(bool drw_state)
void DRW_gpu_context_activate(bool drw_state)
{
if (!BLI_thread_is_main()) {
return;
}
if (drw_state) {
WM_opengl_context_activate(DST.gl_context);
GPU_context_active_set(DST.gpu_context);
WM_system_gpu_context_activate(DST.system_gpu_context);
GPU_context_active_set(DST.blender_gpu_context);
}
else {
wm_window_reset_drawable();

View File

@ -666,13 +666,13 @@ typedef struct DRWManager {
/* ---------- Nothing after this point is cleared after use ----------- */
/* gl_context serves as the offset for clearing only
/* system_gpu_context serves as the offset for clearing only
* the top portion of the struct so DO NOT MOVE IT! */
/** Unique ghost context used by the draw manager. */
void *gl_context;
GPUContext *gpu_context;
void *system_gpu_context;
GPUContext *blender_gpu_context;
/** Mutex to lock the drw manager and avoid concurrent context usage. */
TicketMutex *gl_context_mutex;
TicketMutex *system_gpu_context_mutex;
GPUDrawList *draw_list;

View File

@ -59,8 +59,8 @@ typedef struct DRWShaderCompiler {
/** Optimization queue. */
ListBase optimize_queue; /* GPUMaterial */
void *gl_context;
GPUContext *gpu_context;
void *system_gpu_context;
GPUContext *blender_gpu_context;
bool own_context;
} DRWShaderCompiler;
@ -74,20 +74,20 @@ static void drw_deferred_shader_compilation_exec(
{
GPU_render_begin();
DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data;
void *gl_context = comp->gl_context;
GPUContext *gpu_context = comp->gpu_context;
void *system_gpu_context = comp->system_gpu_context;
GPUContext *blender_gpu_context = comp->blender_gpu_context;
BLI_assert(gl_context != NULL);
BLI_assert(gpu_context != NULL);
BLI_assert(system_gpu_context != NULL);
BLI_assert(blender_gpu_context != NULL);
const bool use_main_context_workaround = GPU_use_main_context_workaround();
if (use_main_context_workaround) {
BLI_assert(gl_context == DST.gl_context);
BLI_assert(system_gpu_context == DST.system_gpu_context);
GPU_context_main_lock();
}
WM_opengl_context_activate(gl_context);
GPU_context_active_set(gpu_context);
WM_system_gpu_context_activate(system_gpu_context);
GPU_context_active_set(blender_gpu_context);
while (true) {
if (*stop != 0) {
@ -145,7 +145,7 @@ static void drw_deferred_shader_compilation_exec(
}
GPU_context_active_set(NULL);
WM_opengl_context_release(gl_context);
WM_system_gpu_context_release(system_gpu_context);
if (use_main_context_workaround) {
GPU_context_main_unlock();
}
@ -163,10 +163,10 @@ static void drw_deferred_shader_compilation_free(void *custom_data)
if (comp->own_context) {
/* Only destroy if the job owns the context. */
WM_opengl_context_activate(comp->gl_context);
GPU_context_active_set(comp->gpu_context);
GPU_context_discard(comp->gpu_context);
WM_opengl_context_dispose(comp->gl_context);
WM_system_gpu_context_activate(comp->system_gpu_context);
GPU_context_active_set(comp->blender_gpu_context);
GPU_context_discard(comp->blender_gpu_context);
WM_system_gpu_context_dispose(comp->system_gpu_context);
wm_window_reset_drawable();
}
@ -204,9 +204,9 @@ static void drw_deferred_queue_append(GPUMaterial *mat, bool is_optimization_job
BLI_movelisttolist(&comp->optimize_queue, &old_comp->optimize_queue);
BLI_spin_unlock(&old_comp->list_lock);
/* Do not recreate context, just pass ownership. */
if (old_comp->gl_context) {
comp->gl_context = old_comp->gl_context;
comp->gpu_context = old_comp->gpu_context;
if (old_comp->system_gpu_context) {
comp->system_gpu_context = old_comp->system_gpu_context;
comp->blender_gpu_context = old_comp->blender_gpu_context;
old_comp->own_context = false;
comp->own_context = job_own_context;
}
@ -226,18 +226,18 @@ static void drw_deferred_queue_append(GPUMaterial *mat, bool is_optimization_job
}
/* Create only one context. */
if (comp->gl_context == NULL) {
if (comp->system_gpu_context == NULL) {
if (use_main_context) {
comp->gl_context = DST.gl_context;
comp->gpu_context = DST.gpu_context;
comp->system_gpu_context = DST.system_gpu_context;
comp->blender_gpu_context = DST.blender_gpu_context;
}
else {
comp->gl_context = WM_opengl_context_create();
comp->gpu_context = GPU_context_create(NULL, comp->gl_context);
comp->system_gpu_context = WM_system_gpu_context_create();
comp->blender_gpu_context = GPU_context_create(NULL, comp->system_gpu_context);
GPU_context_active_set(NULL);
WM_opengl_context_activate(DST.gl_context);
GPU_context_active_set(DST.gpu_context);
WM_system_gpu_context_activate(DST.system_gpu_context);
GPU_context_active_set(DST.blender_gpu_context);
}
comp->own_context = job_own_context;
}

View File

@ -53,7 +53,7 @@ uint *DRW_select_buffer_read(
if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) {
SELECTID_Context *select_ctx = DRW_select_engine_context_get();
DRW_opengl_context_enable();
DRW_gpu_context_enable();
/* Update the drawing. */
DRW_draw_select_id(depsgraph, region, v3d, rect);
@ -84,7 +84,7 @@ uint *DRW_select_buffer_read(
}
GPU_framebuffer_restore();
DRW_opengl_context_disable();
DRW_gpu_context_disable();
}
if (r_buf_len) {

View File

@ -175,9 +175,9 @@ struct ObjectInfos {
float4 infos;
#else
/** Uploaded as center + size. Converted to mul+bias to local coord. */
float3 orco_add;
packed_float3 orco_add;
uint object_attrs_offset;
float3 orco_mul;
packed_float3 orco_mul;
uint object_attrs_len;
float4 ob_color;

View File

@ -29,27 +29,27 @@ void main()
vec3 diagonal = p01 + p02 + p03;
vec3 center = p0 + diagonal * 0.5;
float min_axis = min_v3(abs(diagonal));
bounds_buf[resource_id].bounding_sphere.xyz = transform_point(model_mat, center);
bounds.bounding_sphere.xyz = transform_point(model_mat, center);
/* We have to apply scaling to the diagonal. */
bounds_buf[resource_id].bounding_sphere.w = length(transform_direction(model_mat, diagonal)) *
0.5;
bounds_buf[resource_id]._inner_sphere_radius = min_axis;
bounds_buf[resource_id].bounding_corners[0].xyz = transform_point(model_mat, p0);
bounds_buf[resource_id].bounding_corners[1].xyz = transform_direction(model_mat, p01);
bounds_buf[resource_id].bounding_corners[2].xyz = transform_direction(model_mat, p02);
bounds_buf[resource_id].bounding_corners[3].xyz = transform_direction(model_mat, p03);
bounds.bounding_sphere.w = length(transform_direction(model_mat, diagonal)) * 0.5;
bounds._inner_sphere_radius = min_axis;
bounds.bounding_corners[0].xyz = transform_point(model_mat, p0);
bounds.bounding_corners[1].xyz = transform_direction(model_mat, p01);
bounds.bounding_corners[2].xyz = transform_direction(model_mat, p02);
bounds.bounding_corners[3].xyz = transform_direction(model_mat, p03);
/* Always have correct handedness in the corners vectors. */
if (flag_test(infos.flag, OBJECT_NEGATIVE_SCALE)) {
bounds_buf[resource_id].bounding_corners[0].xyz +=
bounds_buf[resource_id].bounding_corners[1].xyz;
bounds_buf[resource_id].bounding_corners[1].xyz =
-bounds_buf[resource_id].bounding_corners[1].xyz;
bounds.bounding_corners[0].xyz += bounds.bounding_corners[1].xyz;
bounds.bounding_corners[1].xyz = -bounds.bounding_corners[1].xyz;
}
/* TODO: Bypass test for very large objects (see #67319). */
if (bounds_buf[resource_id].bounding_sphere.w > 1e12) {
bounds_buf[resource_id].bounding_sphere.w = -1.0;
if (bounds.bounding_sphere.w > 1e12) {
bounds.bounding_sphere.w = -1.0;
}
/* Update bounds. */
bounds_buf[resource_id] = bounds;
}
vec3 loc = infos.orco_add; /* Box center. */

View File

@ -27,7 +27,7 @@ set(SRC
anim_channels_edit.c
anim_deps.c
anim_draw.c
anim_filter.c
anim_filter.cc
anim_ipo_utils.c
anim_markers.c
anim_motion_paths.c

View File

@ -31,9 +31,9 @@ ID_Type ED_asset_handle_get_id_type(const struct AssetHandle *asset);
int ED_asset_handle_get_preview_icon_id(const struct AssetHandle *asset);
void ED_asset_handle_get_full_library_path(
const struct AssetHandle *asset,
/* `1090` for #FILE_MAX_LIBEXTRA,
/* `1024` for #FILE_MAX,
* rely on warnings to let us know if this gets out of sync. */
char r_full_lib_path[1090]);
char r_full_lib_path[1024]);
bool ED_asset_handle_get_use_relative_path(const struct AssetHandle *asset);
#ifdef __cplusplus

View File

@ -63,7 +63,7 @@ blender::StringRefNull ED_asset_handle_get_relative_path(const AssetHandle &asse
}
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
char r_full_lib_path[FILE_MAX_LIBEXTRA])
char r_full_lib_path[FILE_MAX])
{
*r_full_lib_path = '\0';
@ -73,7 +73,7 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
return;
}
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX_LIBEXTRA);
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
}
bool ED_asset_handle_get_use_relative_path(const AssetHandle *asset)

View File

@ -11751,6 +11751,7 @@ bool UI_textbutton_activate_rna(const bContext *C,
if (but_text) {
ARegion *region_ctx = CTX_wm_region(C);
/* Temporary context override for activating the button. */
CTX_wm_region_set(const_cast<bContext *>(C), region);
UI_but_active_only(C, region, block_text, but_text);
CTX_wm_region_set(const_cast<bContext *>(C), region_ctx);

View File

@ -503,7 +503,7 @@ void paintface_select_loop(bContext *C, Object *ob, const int mval[2], const boo
edge_to_poly_map,
polys_to_select);
if (!traced_full_loop) {
if (!traced_full_loop && polys_to_closest_edge.size() > 1) {
/* Trace the other way. */
follow_face_loop(polys_to_closest_edge[1],
closest_edge_index,
@ -519,8 +519,11 @@ void paintface_select_loop(bContext *C, Object *ob, const int mval[2], const boo
/* Toggling behavior. When one of the faces of the picked edge is already selected,
* it deselects the loop instead. */
const bool select_toggle = select && !(select_poly.span[polys_to_closest_edge[0]] ||
select_poly.span[polys_to_closest_edge[1]]);
bool any_adjacent_poly_selected = false;
for (const int i : polys_to_closest_edge) {
any_adjacent_poly_selected |= select_poly.span[i];
}
const bool select_toggle = select && !any_adjacent_poly_selected;
select_poly.span.fill_indices(polys_to_select.as_span(), select_toggle);
select_poly.finish();

View File

@ -1088,7 +1088,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
RE_current_scene_update_cb(re, rj, current_scene_update);
RE_stats_draw_cb(re, rj, image_renderinfo_cb);
RE_progress_cb(re, rj, render_progress_update);
RE_gl_context_create(re);
RE_system_gpu_context_create(re);
rj->re = re;
G.is_break = false;

View File

@ -302,7 +302,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
uchar *gp_rect;
uchar *render_rect = ibuf_result->byte_buffer.data;
DRW_opengl_context_enable();
DRW_gpu_context_enable();
GPU_offscreen_bind(oglrender->ofs, true);
GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
@ -324,7 +324,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
}
GPU_offscreen_unbind(oglrender->ofs, true);
DRW_opengl_context_disable();
DRW_gpu_context_disable();
MEM_freeN(gp_rect);
}
@ -744,14 +744,14 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
BKE_render_resolution(&scene->r, false, &sizex, &sizey);
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
DRW_opengl_context_enable(); /* Off-screen creation needs to be done in DRW context. */
DRW_gpu_context_enable(); /* Off-screen creation needs to be done in DRW context. */
ofs = GPU_offscreen_create(sizex,
sizey,
true,
GPU_RGBA16F,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ,
err_out);
DRW_opengl_context_disable();
DRW_gpu_context_disable();
if (!ofs) {
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
@ -925,9 +925,9 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
DRW_opengl_context_enable();
DRW_gpu_context_enable();
GPU_offscreen_free(oglrender->ofs);
DRW_opengl_context_disable();
DRW_gpu_context_disable();
if (oglrender->is_sequencer) {
MEM_freeN(oglrender->seq_data.ibufs_arr);

View File

@ -243,7 +243,7 @@ static void compo_initjob(void *cjv)
}
cj->re = RE_NewSceneRender(scene);
RE_gl_context_create(cj->re);
RE_system_gpu_context_create(cj->re);
}
/* Called before redraw notifiers, it moves finished previews over. */
@ -302,7 +302,7 @@ static void compo_startjob(void *cjv,
}
}
RE_gl_context_destroy(cj->re);
RE_system_gpu_context_destroy(cj->re);
ntree->runtime->test_break = nullptr;
ntree->runtime->stats_draw = nullptr;

View File

@ -1899,7 +1899,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
}
const bool own_ofs = (ofs == nullptr);
DRW_opengl_context_enable();
DRW_gpu_context_enable();
if (own_ofs) {
/* bind */
@ -1910,7 +1910,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ,
err_out);
if (ofs == nullptr) {
DRW_opengl_context_disable();
DRW_gpu_context_disable();
return nullptr;
}
}
@ -2006,7 +2006,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
GPU_offscreen_free(ofs);
}
DRW_opengl_context_disable();
DRW_gpu_context_disable();
if (old_fb) {
GPU_framebuffer_bind(old_fb);

View File

@ -666,7 +666,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
/* All of the queries need to be perform on the drawing context. */
DRW_opengl_context_enable();
DRW_gpu_context_enable();
G.f |= G_FLAG_PICKSEL;
@ -746,7 +746,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
GPU_depth_test(GPU_DEPTH_NONE);
}
DRW_opengl_context_disable();
DRW_gpu_context_disable();
UI_Theme_Restore(&theme_state);

View File

@ -215,6 +215,7 @@ set(VULKAN_SRC
vulkan/vk_drawlist.cc
vulkan/vk_fence.cc
vulkan/vk_framebuffer.cc
vulkan/vk_image_view.cc
vulkan/vk_immediate.cc
vulkan/vk_index_buffer.cc
vulkan/vk_memory.cc
@ -250,6 +251,7 @@ set(VULKAN_SRC
vulkan/vk_drawlist.hh
vulkan/vk_fence.hh
vulkan/vk_framebuffer.hh
vulkan/vk_image_view.hh
vulkan/vk_immediate.hh
vulkan/vk_index_buffer.hh
vulkan/vk_memory.hh

View File

@ -60,7 +60,7 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport,
float dither);
/**
* Should be called from DRW after DRW_opengl_context_enable.
* Should be called from DRW after DRW_gpu_context_enable.
*/
void GPU_viewport_bind_from_offscreen(GPUViewport *viewport,
struct GPUOffScreen *ofs,

View File

@ -43,21 +43,21 @@ void ShaderBuilder::init()
{
CLG_init();
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
switch (GPU_backend_type_selection_get()) {
case GPU_BACKEND_OPENGL:
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
break;
#ifdef WITH_METAL_BACKEND
case GPU_BACKEND_METAL:
glSettings.context_type = GHOST_kDrawingContextTypeMetal;
gpuSettings.context_type = GHOST_kDrawingContextTypeMetal;
break;
#endif
#ifdef WITH_VULKAN_BACKEND
case GPU_BACKEND_VULKAN:
glSettings.context_type = GHOST_kDrawingContextTypeVulkan;
gpuSettings.context_type = GHOST_kDrawingContextTypeVulkan;
break;
#endif
@ -67,8 +67,8 @@ void ShaderBuilder::init()
}
ghost_system_ = GHOST_CreateSystemBackground();
ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings);
GHOST_ActivateOpenGLContext(ghost_context_);
ghost_context_ = GHOST_CreateGPUContext(ghost_system_, gpuSettings);
GHOST_ActivateGPUContext(ghost_context_);
gpu_context_ = GPU_context_create(nullptr, ghost_context_);
GPU_init();
@ -80,7 +80,7 @@ void ShaderBuilder::exit()
GPU_context_discard(gpu_context_);
GHOST_DisposeOpenGLContext(ghost_system_, ghost_context_);
GHOST_DisposeGPUContext(ghost_system_, ghost_context_);
GHOST_DisposeSystem(ghost_system_);
CLG_exit();

View File

@ -194,7 +194,7 @@ void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect)
rect_size[0] = BLI_rcti_size_x(rect) + 1;
rect_size[1] = BLI_rcti_size_y(rect) + 1;
DRW_opengl_context_enable();
DRW_gpu_context_enable();
if (!equals_v2v2_int(viewport->size, rect_size)) {
copy_v2_v2_int(viewport->size, rect_size);
@ -562,7 +562,7 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport,
void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
{
GPU_framebuffer_restore();
DRW_opengl_context_disable();
DRW_gpu_context_disable();
}
int GPU_viewport_active_view_get(GPUViewport *viewport)

View File

@ -51,7 +51,7 @@ GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list
ghost_window_ = ghost_window;
if (ghost_window) {
GLuint default_fbo = GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window);
GLuint default_fbo = GHOST_GetDefaultGPUFramebuffer((GHOST_WindowHandle)ghost_window);
GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window);
int w = GHOST_GetWidthRectangle(bounds);
int h = GHOST_GetHeightRectangle(bounds);

View File

@ -66,7 +66,7 @@ using uvec4 = uint4;
/* Compute decorators. */
#define TG threadgroup
#define barrier() threadgroup_barrier(mem_flags::mem_threadgroup)
#define barrier() threadgroup_barrier(mem_flags::mem_threadgroup | mem_flags::mem_device | mem_flags::mem_texture)
#ifdef MTL_USE_WORKGROUP_SIZE
/* Compute workgroup size. */

View File

@ -24,12 +24,12 @@ void GPUTest::SetUp()
CLG_init();
GPU_backend_type_selection_set(gpu_backend_type);
GHOST_GLSettings glSettings = {};
glSettings.context_type = draw_context_type;
glSettings.flags = GHOST_glDebugContext;
GHOST_GPUSettings gpuSettings = {};
gpuSettings.context_type = draw_context_type;
gpuSettings.flags = GHOST_gpuDebugContext;
ghost_system = GHOST_CreateSystem();
ghost_context = GHOST_CreateOpenGLContext(ghost_system, glSettings);
GHOST_ActivateOpenGLContext(ghost_context);
ghost_context = GHOST_CreateGPUContext(ghost_system, gpuSettings);
GHOST_ActivateGPUContext(ghost_context);
context = GPU_context_create(nullptr, ghost_context);
GPU_init();
@ -46,7 +46,7 @@ void GPUTest::TearDown()
GPU_exit();
GPU_context_discard(context);
GHOST_DisposeOpenGLContext(ghost_system, ghost_context);
GHOST_DisposeGPUContext(ghost_system, ghost_context);
GHOST_DisposeSystem(ghost_system);
CLG_exit();

View File

@ -174,7 +174,7 @@ void VKDescriptorSetTracker::update(VKContext &context)
binding.texture->layout_ensure(context, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VkDescriptorImageInfo image_info = {};
image_info.sampler = binding.vk_sampler;
image_info.imageView = binding.texture->vk_image_view_handle();
image_info.imageView = binding.texture->image_view_get().vk_handle();
image_info.imageLayout = binding.texture->current_layout_get();
image_infos.append(image_info);

View File

@ -372,6 +372,8 @@ void VKFrameBuffer::render_pass_create()
std::array<VkAttachmentDescription, GPU_FB_MAX_ATTACHMENT> attachment_descriptions;
std::array<VkImageView, GPU_FB_MAX_ATTACHMENT> image_views;
std::array<VkAttachmentReference, GPU_FB_MAX_ATTACHMENT> attachment_references;
image_views_.clear();
bool has_depth_attachment = false;
bool found_attachment = false;
int depth_location = -1;
@ -402,7 +404,8 @@ void VKFrameBuffer::render_pass_create()
/* Ensure texture is allocated to ensure the image view. */
VKTexture &texture = *static_cast<VKTexture *>(unwrap(attachment.tex));
texture.ensure_allocated();
image_views[attachment_location] = texture.vk_image_view_handle();
image_views_.append(VKImageView(texture, attachment.mip, name_));
image_views[attachment_location] = image_views_.last().vk_handle();
VkAttachmentDescription &attachment_description =
attachment_descriptions[attachment_location];
@ -411,10 +414,10 @@ void VKFrameBuffer::render_pass_create()
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment_description.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
attachment_description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.initialLayout = texture.current_layout_get();
attachment_description.finalLayout = texture.current_layout_get();
/* Create the attachment reference. */
const bool is_depth_attachment = ELEM(
@ -497,6 +500,7 @@ void VKFrameBuffer::render_pass_free()
vkDestroyRenderPass(device.device_get(), vk_render_pass_, vk_allocation_callbacks);
vkDestroyFramebuffer(device.device_get(), vk_framebuffer_, vk_allocation_callbacks);
}
image_views_.clear();
vk_render_pass_ = VK_NULL_HANDLE;
vk_framebuffer_ = VK_NULL_HANDLE;
}

View File

@ -15,6 +15,7 @@
#include "gpu_framebuffer_private.hh"
#include "vk_common.hh"
#include "vk_image_view.hh"
namespace blender::gpu {
@ -41,6 +42,8 @@ class VKFrameBuffer : public FrameBuffer {
*/
bool flip_viewport_ = false;
Vector<VKImageView, GPU_FB_MAX_ATTACHMENT> image_views_;
public:
/**
* Create a conventional framebuffer to attach texture to.

View File

@ -0,0 +1,68 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include "vk_image_view.hh"
#include "vk_backend.hh"
#include "vk_debug.hh"
#include "vk_device.hh"
#include "vk_memory.hh"
#include "vk_texture.hh"
namespace blender::gpu {
VKImageView::VKImageView(VKTexture &texture, int mip_level, StringRefNull name)
: vk_image_view_(create_vk_image_view(texture, mip_level, name))
{
BLI_assert(vk_image_view_ != VK_NULL_HANDLE);
}
VKImageView::VKImageView(VkImageView vk_image_view) : vk_image_view_(vk_image_view)
{
BLI_assert(vk_image_view_ != VK_NULL_HANDLE);
}
VKImageView::VKImageView(VKImageView &&other)
{
vk_image_view_ = other.vk_image_view_;
other.vk_image_view_ = VK_NULL_HANDLE;
}
VKImageView::~VKImageView()
{
if (vk_image_view_ != VK_NULL_HANDLE) {
VK_ALLOCATION_CALLBACKS
const VKDevice &device = VKBackend::get().device_get();
vkDestroyImageView(device.device_get(), vk_image_view_, vk_allocation_callbacks);
}
}
VkImageView VKImageView::create_vk_image_view(VKTexture &texture,
int mip_level,
StringRefNull name)
{
VK_ALLOCATION_CALLBACKS
VkImageViewCreateInfo image_view_info = {};
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_info.image = texture.vk_image_handle();
image_view_info.viewType = to_vk_image_view_type(texture.type_get());
image_view_info.format = to_vk_format(texture.format_get());
image_view_info.components = to_vk_component_mapping(texture.format_get());
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(texture.format_get());
image_view_info.subresourceRange.baseMipLevel = mip_level;
image_view_info.subresourceRange.levelCount = 1;
image_view_info.subresourceRange.baseArrayLayer = 0;
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
const VKDevice &device = VKBackend::get().device_get();
VkImageView image_view = VK_NULL_HANDLE;
vkCreateImageView(device.device_get(), &image_view_info, vk_allocation_callbacks, &image_view);
debug::object_label(image_view, name.c_str());
return image_view;
}
} // namespace blender::gpu

View File

@ -0,0 +1,44 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#pragma once
#include "vk_common.hh"
#include "BLI_string_ref.hh"
#include "BLI_utility_mixins.hh"
namespace blender::gpu {
class VKTexture;
class VKImageView : NonCopyable {
VkImageView vk_image_view_ = VK_NULL_HANDLE;
public:
VKImageView(VKTexture &texture, int mip_level, StringRefNull name);
/**
* Wrap the given vk_image_view handle. Note that the vk_image_view handle ownership is
* transferred to VKImageView.
*/
VKImageView(VkImageView vk_image_view);
VKImageView(VKImageView &&other);
~VKImageView();
VkImageView vk_handle() const
{
BLI_assert(vk_image_view_ != VK_NULL_HANDLE);
return vk_image_view_;
}
private:
static VkImageView create_vk_image_view(VKTexture &texture, int mip_level, StringRefNull name);
};
} // namespace blender::gpu

View File

@ -25,11 +25,9 @@ namespace blender::gpu {
VKTexture::~VKTexture()
{
VK_ALLOCATION_CALLBACKS
if (is_allocated()) {
const VKDevice &device = VKBackend::get().device_get();
vmaDestroyImage(device.mem_allocator_get(), vk_image_, allocation_);
vkDestroyImageView(device.device_get(), vk_image_view_, vk_allocation_callbacks);
}
}
@ -83,6 +81,9 @@ void VKTexture::generate_mipmap()
*this,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
Span<VkImageBlit>(&image_blit, 1));
/* TODO: Until we do actual command encoding we need to submit each transfer operation
* individually. */
command_buffer.submit();
}
/* Ensure that all mipmap levels are in `VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL`. All miplevels are
* except the last one. */
@ -148,9 +149,12 @@ void VKTexture::swizzle_set(const char /*swizzle_mask*/[4])
NOT_YET_IMPLEMENTED;
}
void VKTexture::mip_range_set(int /*min*/, int /*max*/)
void VKTexture::mip_range_set(int min, int max)
{
NOT_YET_IMPLEMENTED;
mip_min_ = min;
mip_max_ = max;
flags_ |= IMAGE_VIEW_DIRTY;
}
void VKTexture::read_sub(int mip, eGPUDataFormat format, const int area[4], void *r_data)
@ -430,20 +434,6 @@ bool VKTexture::allocate()
/* Promote image to the correct layout. */
layout_ensure(context, VK_IMAGE_LAYOUT_GENERAL);
VK_ALLOCATION_CALLBACKS
VkImageViewCreateInfo image_view_info = {};
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_info.image = vk_image_;
image_view_info.viewType = to_vk_image_view_type(type_);
image_view_info.format = to_vk_format(format_);
image_view_info.components = to_vk_component_mapping(format_);
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
image_view_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
result = vkCreateImageView(
device.device_get(), &image_view_info, vk_allocation_callbacks, &vk_image_view_);
debug::object_label(vk_image_view_, name_);
return result == VK_SUCCESS;
}
@ -525,6 +515,48 @@ void VKTexture::layout_ensure(VKContext &context,
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
context.command_buffer_get().pipeline_barrier(Span<VkImageMemoryBarrier>(&barrier, 1));
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Image Views
* \{ */
void VKTexture::image_view_ensure()
{
if (flags_ & IMAGE_VIEW_DIRTY) {
image_view_update();
flags_ &= ~IMAGE_VIEW_DIRTY;
}
}
void VKTexture::image_view_update()
{
VK_ALLOCATION_CALLBACKS
VkImageViewCreateInfo image_view_info = {};
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_info.image = vk_image_;
image_view_info.viewType = to_vk_image_view_type(type_);
image_view_info.format = to_vk_format(format_);
image_view_info.components = to_vk_component_mapping(format_);
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
IndexRange mip_range = mip_map_range();
image_view_info.subresourceRange.baseMipLevel = mip_range.first();
image_view_info.subresourceRange.levelCount = mip_range.size();
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
const VKDevice &device = VKBackend::get().device_get();
VkImageView image_view = VK_NULL_HANDLE;
vkCreateImageView(device.device_get(), &image_view_info, vk_allocation_callbacks, &image_view);
debug::object_label(image_view, name_);
image_view_.emplace(image_view);
}
IndexRange VKTexture::mip_map_range() const
{
return IndexRange(mip_min_, mip_max_ - mip_min_ + 1);
}
/** \} */
} // namespace blender::gpu

View File

@ -9,7 +9,9 @@
#pragma once
#include "gpu_texture_private.hh"
#include "vk_context.hh"
#include "vk_image_view.hh"
namespace blender::gpu {
@ -17,15 +19,23 @@ class VKSampler;
class VKTexture : public Texture {
VkImage vk_image_ = VK_NULL_HANDLE;
VkImageView vk_image_view_ = VK_NULL_HANDLE;
VmaAllocation allocation_ = VK_NULL_HANDLE;
/* Image view when used in a shader. */
std::optional<VKImageView> image_view_;
/* Last image layout of the texture. Frame-buffer and barriers can alter/require the actual
* layout to be changed. During this it requires to set the current layout in order to know which
* conversion should happen. #current_layout_ keep track of the layout so the correct conversion
* can be done. */
VkImageLayout current_layout_ = VK_IMAGE_LAYOUT_UNDEFINED;
enum eDirtyFlags {
IMAGE_VIEW_DIRTY = (1 << 0),
};
int flags_ = IMAGE_VIEW_DIRTY;
public:
VKTexture(const char *name) : Texture(name) {}
@ -58,11 +68,6 @@ class VKTexture : public Texture {
BLI_assert(vk_image_ != VK_NULL_HANDLE);
return vk_image_;
}
VkImageView vk_image_view_handle() const
{
BLI_assert(is_allocated());
return vk_image_view_;
}
void ensure_allocated();
@ -123,6 +128,23 @@ class VKTexture : public Texture {
VkImageLayout requested_layout);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Image Views
* \{ */
public:
VKImageView &image_view_get()
{
image_view_ensure();
return *image_view_;
}
private:
IndexRange mip_map_range() const;
void image_view_ensure();
void image_view_update();
/** \} */
};
static inline VKTexture *unwrap(Texture *tex)

View File

@ -881,6 +881,12 @@ typedef struct NodeBilateralBlurData {
char _pad[2];
} NodeBilateralBlurData;
typedef struct NodeKuwaharaData {
short size;
short variation;
int smoothing;
} NodeKuwaharaData;
typedef struct NodeAntiAliasingData {
float threshold;
float contrast_limit;
@ -2136,6 +2142,12 @@ typedef enum CMPNodeGlareType {
CMP_NODE_GLARE_GHOST = 3,
} CMPNodeGlareType;
/* Kuwahara Node. Stored in variation */
typedef enum CMPNodeKuwahara {
CMP_NODE_KUWAHARA_CLASSIC = 0,
CMP_NODE_KUWAHARA_ANISOTROPIC = 1,
} CMPNodeKuwahara;
/* Stabilize 2D node. Stored in custom1. */
typedef enum CMPNodeStabilizeInterpolation {
CMP_NODE_STABILIZE_INTERPOLATION_NEAREST = 0,

View File

@ -522,7 +522,7 @@ enum {
/** #MovieTrackingTrack.pattern_match */
typedef enum eTrackFrameMatch {
TRACK_MATCH_KEYFRAME = 0,
TRACK_MATCH_PREVIOS_FRAME = 1,
TRACK_MATCH_PREVIOUS_FRAME = 1,
} eTrackFrameMatch;
/** #MovieTrackingSettings.motion_flag */

View File

@ -9374,6 +9374,43 @@ static void def_cmp_denoise(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_kuwahara(StructRNA *srna)
{
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeKuwaharaData", "storage");
static const EnumPropertyItem variation_items[] = {
{0, "CLASSIC", 0, "Classic", "Fast but less accurate variation"},
{1, "ANISOTROPIC", 0, "Anisotropic", "Accurate but slower variation"},
{0, NULL, 0, NULL, NULL},
};
prop = RNA_def_property(srna, "size", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "size");
RNA_def_property_range(prop, 1.0, 100.0);
RNA_def_property_ui_range(prop, 1, 100, 1, -1);
RNA_def_property_ui_text(
prop, "Size", "Size of filter. Larger values give stronger stylized effect");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "variation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "variation");
RNA_def_property_enum_items(prop, variation_items);
RNA_def_property_ui_text(prop, "", "Variation of Kuwahara filter to use");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "smoothing", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "smoothing");
RNA_def_property_range(prop, 0.0, 50.0);
RNA_def_property_ui_range(prop, 0, 50, 1, -1);
RNA_def_property_ui_text(prop,
"Smoothing",
"Smoothing degree before applying filter. Higher values remove details "
"and give smoother edges");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_antialiasing(StructRNA *srna)
{
PropertyRNA *prop;

View File

@ -2082,7 +2082,7 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSE
}
}
RNA_enum_item_end(&item, &totitem);
RNA_enum_item_end(&item, &totitem_added);
*r_free = true;
return item;

View File

@ -900,7 +900,7 @@ static const EnumPropertyItem tracker_motion_model[] = {
static const EnumPropertyItem pattern_match_items[] = {
{TRACK_MATCH_KEYFRAME, "KEYFRAME", 0, "Keyframe", "Track pattern from keyframe to next frame"},
{TRACK_MATCH_PREVIOS_FRAME,
{TRACK_MATCH_PREVIOUS_FRAME,
"PREV_FRAME",
0,
"Previous frame",

View File

@ -224,6 +224,7 @@ DefNode(CompositorNode, CMP_NODE_COMBINE_XYZ, 0, "COMBIN
DefNode(CompositorNode, CMP_NODE_SEPARATE_XYZ, 0, "SEPARATE_XYZ", SeparateXYZ, "Separate XYZ", "" )
DefNode(CompositorNode, CMP_NODE_SEPARATE_COLOR, def_cmp_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "" )
DefNode(CompositorNode, CMP_NODE_COMBINE_COLOR, def_cmp_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "" )
DefNode(CompositorNode, CMP_NODE_KUWAHARA, def_cmp_kuwahara, "KUWAHARA", Kuwahara, "Kuwahara", "" )
DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )

View File

@ -77,6 +77,7 @@ set(SRC
nodes/node_composite_invert.cc
nodes/node_composite_keying.cc
nodes/node_composite_keyingscreen.cc
nodes/node_composite_kuwahara.cc
nodes/node_composite_lensdist.cc
nodes/node_composite_levels.cc
nodes/node_composite_luma_matte.cc

View File

@ -64,6 +64,7 @@ void register_composite_nodes()
register_node_type_cmp_invert();
register_node_type_cmp_keying();
register_node_type_cmp_keyingscreen();
register_node_type_cmp_kuwahara();
register_node_type_cmp_lensdist();
register_node_type_cmp_luma_matte();
register_node_type_cmp_map_range();

View File

@ -60,6 +60,7 @@ void register_node_type_cmp_inpaint();
void register_node_type_cmp_invert();
void register_node_type_cmp_keying();
void register_node_type_cmp_keyingscreen();
void register_node_type_cmp_kuwahara();
void register_node_type_cmp_lensdist();
void register_node_type_cmp_luma_matte();
void register_node_type_cmp_map_range();

View File

@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation */
/** \file
* \ingroup cmpnodes
*/
#include "COM_node_operation.hh"
/* **************** Kuwahara ******************** */
namespace blender::nodes::node_composite_kuwahara_cc {
NODE_STORAGE_FUNCS(NodeKuwaharaData)
static void cmp_node_kuwahara_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Color>(N_("Image"))
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
.compositor_domain_priority(0);
b.add_output<decl::Color>(N_("Image"));
}
static void node_composit_init_kuwahara(bNodeTree * /*ntree*/, bNode *node)
{
NodeKuwaharaData *data = MEM_cnew<NodeKuwaharaData>(__func__);
node->storage = data;
/* Set defaults. */
data->size = 4;
data->smoothing = 2;
}
static void node_composit_buts_kuwahara(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiLayout *col;
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "variation", 0, nullptr, ICON_NONE);
uiItemR(col, ptr, "size", 0, nullptr, ICON_NONE);
const int variation = RNA_enum_get(ptr, "variation");
if (variation == CMP_NODE_KUWAHARA_ANISOTROPIC) {
uiItemR(col, ptr, "smoothing", 0, nullptr, ICON_NONE);
}
}
using namespace blender::realtime_compositor;
class ConvertKuwaharaOperation : public NodeOperation {
public:
using NodeOperation::NodeOperation;
void execute() override
{
get_input("Image").pass_through(get_result("Image"));
context().set_info_message("Viewport compositor setup not fully supported");
}
};
static NodeOperation *get_compositor_operation(Context &context, DNode node)
{
return new ConvertKuwaharaOperation(context, node);
}
} // namespace blender::nodes::node_composite_kuwahara_cc
void register_node_type_cmp_kuwahara()
{
namespace file_ns = blender::nodes::node_composite_kuwahara_cc;
static bNodeType ntype;
cmp_node_type_base(&ntype, CMP_NODE_KUWAHARA, "Kuwahara", NODE_CLASS_OP_FILTER);
ntype.declare = file_ns::cmp_node_kuwahara_declare;
ntype.draw_buttons = file_ns::node_composit_buts_kuwahara;
ntype.initfunc = file_ns::node_composit_init_kuwahara;
node_type_storage(
&ntype, "NodeKuwaharaData", node_free_standard_storage, node_copy_standard_storage);
ntype.get_compositor_operation = file_ns::get_compositor_operation;
ntype.realtime_compositor_unsupported_message = N_(
"Node not supported in the Viewport compositor");
nodeRegisterType(&ntype);
}

View File

@ -9,15 +9,22 @@
#include "UI_interface.h"
#include "UI_resources.h"
#include "GPU_shader.h"
#include "COM_node_operation.hh"
#include "COM_utilities.hh"
#include "node_composite_util.hh"
namespace blender::nodes::node_composite_sunbeams_cc {
NODE_STORAGE_FUNCS(NodeSunBeams)
static void cmp_node_sunbeams_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Color>("Image").default_value({1.0f, 1.0f, 1.0f, 1.0f});
b.add_input<decl::Color>("Image")
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
.compositor_domain_priority(0);
b.add_output<decl::Color>("Image");
}
@ -49,8 +56,27 @@ class SunBeamsOperation : public NodeOperation {
void execute() override
{
get_input("Image").pass_through(get_result("Image"));
context().set_info_message("Viewport compositor setup not fully supported");
GPUShader *shader = shader_manager().get("compositor_sun_beams");
GPU_shader_bind(shader);
GPU_shader_uniform_2fv(shader, "source", node_storage(bnode()).source);
GPU_shader_uniform_1f(shader, "max_ray_length", node_storage(bnode()).ray_length);
const Result &input_image = get_input("Image");
GPU_texture_filter_mode(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_image.bind_as_texture(shader, "input_tx");
const Domain domain = compute_domain();
Result &output_image = get_result("Image");
output_image.allocate_texture(domain);
output_image.bind_as_image(shader, "output_img");
compute_dispatch_threads_at_least(shader, domain.size);
GPU_shader_unbind();
output_image.unbind_as_image();
input_image.unbind_as_texture();
}
};
@ -74,8 +100,6 @@ void register_node_type_cmp_sunbeams()
node_type_storage(
&ntype, "NodeSunBeams", node_free_standard_storage, node_copy_standard_storage);
ntype.get_compositor_operation = file_ns::get_compositor_operation;
ntype.realtime_compositor_unsupported_message = N_(
"Node not supported in the Viewport compositor");
nodeRegisterType(&ntype);
}

View File

@ -162,10 +162,10 @@ typedef struct RenderEngine {
void *update_render_passes_data;
/* GPU context. */
void *wm_gpu_context; /* WindowManager GPU context -> GHOSTContext. */
ThreadMutex gpu_context_mutex;
void *wm_blender_gpu_context; /* WindowManager GPU context -> GHOSTContext. */
ThreadMutex blender_gpu_context_mutex;
bool use_drw_render_context;
struct GPUContext *gpu_context;
struct GPUContext *blender_gpu_context;
/* Whether to restore DRWState after RenderEngine display pass. */
bool gpu_restore_context;
} RenderEngine;
@ -272,8 +272,6 @@ void RE_engines_init_experimental(void);
void RE_engines_exit(void);
void RE_engines_register(RenderEngineType *render_type);
bool RE_engine_is_opengl(RenderEngineType *render_type);
/**
* Return true if the RenderEngineType has native support for direct loading of Alembic data. For
* Cycles, this also checks that the experimental feature set is enabled.

View File

@ -426,10 +426,10 @@ void RE_current_scene_update_cb(struct Render *re,
void *handle,
void (*f)(void *handle, struct Scene *scene));
void RE_gl_context_create(Render *re);
void RE_gl_context_destroy(Render *re);
void *RE_gl_context_get(Render *re);
void *RE_gpu_context_get(Render *re);
void RE_system_gpu_context_create(Render *re);
void RE_system_gpu_context_destroy(Render *re);
void *RE_system_gpu_context_get(Render *re);
void *RE_blender_gpu_context_get(Render *re);
/**
* \param x: ranges from -1 to 1.

View File

@ -115,13 +115,6 @@ bool RE_engine_is_external(const Render *re)
return (re->engine && re->engine->type && re->engine->type->render);
}
bool RE_engine_is_opengl(RenderEngineType *render_type)
{
/* TODO: refine? Can we have OpenGL render engine without OpenGL render pipeline? */
return (render_type->draw_engine != nullptr) &&
DRW_engine_render_support(render_type->draw_engine);
}
bool RE_engine_supports_alembic_procedural(const RenderEngineType *render_type, Scene *scene)
{
if ((render_type->flag & RE_USE_ALEMBIC_PROCEDURAL) == 0) {
@ -143,7 +136,7 @@ RenderEngine *RE_engine_create(RenderEngineType *type)
engine->type = type;
BLI_mutex_init(&engine->update_render_passes_mutex);
BLI_mutex_init(&engine->gpu_context_mutex);
BLI_mutex_init(&engine->blender_gpu_context_mutex);
return engine;
}
@ -176,7 +169,7 @@ void RE_engine_free(RenderEngine *engine)
engine_depsgraph_free(engine);
BLI_mutex_end(&engine->gpu_context_mutex);
BLI_mutex_end(&engine->blender_gpu_context_mutex);
BLI_mutex_end(&engine->update_render_passes_mutex);
MEM_freeN(engine);
@ -1271,7 +1264,7 @@ void RE_engine_tile_highlight_clear_all(RenderEngine *engine)
}
/* -------------------------------------------------------------------- */
/** \name OpenGL context manipulation.
/** \name GPU context manipulation.
*
* GPU context for engine to create and update GPU resources in its own thread,
* without blocking the main thread. Used by Cycles' display driver to create
@ -1282,7 +1275,7 @@ void RE_engine_tile_highlight_clear_all(RenderEngine *engine)
bool RE_engine_gpu_context_create(RenderEngine *engine)
{
/* If the there already is a draw manager render context available, reuse it. */
engine->use_drw_render_context = (engine->re && RE_gl_context_get(engine->re));
engine->use_drw_render_context = (engine->re && RE_system_gpu_context_get(engine->re));
if (engine->use_drw_render_context) {
return true;
}
@ -1291,49 +1284,49 @@ bool RE_engine_gpu_context_create(RenderEngine *engine)
* the main thread here to safely create a context. */
BLI_assert(BLI_thread_is_main());
const bool drw_state = DRW_opengl_context_release();
engine->wm_gpu_context = WM_opengl_context_create();
const bool drw_state = DRW_gpu_context_release();
engine->wm_blender_gpu_context = WM_system_gpu_context_create();
if (engine->wm_gpu_context) {
/* Activate new OpenGL Context for GPUContext creation. */
WM_opengl_context_activate(engine->wm_gpu_context);
if (engine->wm_blender_gpu_context) {
/* Activate new GPU Context for GPUContext creation. */
WM_system_gpu_context_activate(engine->wm_blender_gpu_context);
/* Requires GPUContext for usage of GPU Module for displaying results. */
engine->gpu_context = GPU_context_create(nullptr, engine->wm_gpu_context);
engine->blender_gpu_context = GPU_context_create(nullptr, engine->wm_blender_gpu_context);
GPU_context_active_set(nullptr);
/* Deactivate newly created OpenGL Context, as it is not needed until
/* Deactivate newly created GPU Context, as it is not needed until
* `RE_engine_gpu_context_enable` is called. */
WM_opengl_context_release(engine->wm_gpu_context);
WM_system_gpu_context_release(engine->wm_blender_gpu_context);
}
else {
engine->gpu_context = nullptr;
engine->blender_gpu_context = nullptr;
}
DRW_opengl_context_activate(drw_state);
DRW_gpu_context_activate(drw_state);
return engine->wm_gpu_context != nullptr;
return engine->wm_blender_gpu_context != nullptr;
}
void RE_engine_gpu_context_destroy(RenderEngine *engine)
{
if (!engine->wm_gpu_context) {
if (!engine->wm_blender_gpu_context) {
return;
}
const bool drw_state = DRW_opengl_context_release();
const bool drw_state = DRW_gpu_context_release();
WM_opengl_context_activate(engine->wm_gpu_context);
if (engine->gpu_context) {
WM_system_gpu_context_activate(engine->wm_blender_gpu_context);
if (engine->blender_gpu_context) {
GPUContext *restore_context = GPU_context_active_get();
GPU_context_active_set(engine->gpu_context);
GPU_context_discard(engine->gpu_context);
if (restore_context != engine->gpu_context) {
GPU_context_active_set(engine->blender_gpu_context);
GPU_context_discard(engine->blender_gpu_context);
if (restore_context != engine->blender_gpu_context) {
GPU_context_active_set(restore_context);
}
engine->gpu_context = nullptr;
engine->blender_gpu_context = nullptr;
}
WM_opengl_context_dispose(engine->wm_gpu_context);
WM_system_gpu_context_dispose(engine->wm_blender_gpu_context);
DRW_opengl_context_activate(drw_state);
DRW_gpu_context_activate(drw_state);
}
bool RE_engine_gpu_context_enable(RenderEngine *engine)
@ -1343,16 +1336,16 @@ bool RE_engine_gpu_context_enable(RenderEngine *engine)
DRW_render_context_enable(engine->re);
return true;
}
if (engine->wm_gpu_context) {
BLI_mutex_lock(&engine->gpu_context_mutex);
/* If a previous OpenGL/GPUContext was active (DST.gpu_context), we should later restore this
* when disabling the RenderEngine context. */
engine->gpu_restore_context = DRW_opengl_context_release();
if (engine->wm_blender_gpu_context) {
BLI_mutex_lock(&engine->blender_gpu_context_mutex);
/* If a previous GPU/GPUContext was active (DST.blender_gpu_context), we should later
* restore this when disabling the RenderEngine context. */
engine->gpu_restore_context = DRW_gpu_context_release();
/* Activate RenderEngine OpenGL and GPU Context. */
WM_opengl_context_activate(engine->wm_gpu_context);
if (engine->gpu_context) {
GPU_context_active_set(engine->gpu_context);
/* Activate RenderEngine System and Blender GPU Context. */
WM_system_gpu_context_activate(engine->wm_blender_gpu_context);
if (engine->blender_gpu_context) {
GPU_context_active_set(engine->blender_gpu_context);
GPU_render_begin();
}
return true;
@ -1366,15 +1359,15 @@ void RE_engine_gpu_context_disable(RenderEngine *engine)
DRW_render_context_disable(engine->re);
}
else {
if (engine->wm_gpu_context) {
if (engine->gpu_context) {
if (engine->wm_blender_gpu_context) {
if (engine->blender_gpu_context) {
GPU_render_end();
GPU_context_active_set(nullptr);
}
WM_opengl_context_release(engine->wm_gpu_context);
WM_system_gpu_context_release(engine->wm_blender_gpu_context);
/* Restore DRW state context if previously active. */
DRW_opengl_context_activate(engine->gpu_restore_context);
BLI_mutex_unlock(&engine->gpu_context_mutex);
DRW_gpu_context_activate(engine->gpu_restore_context);
BLI_mutex_unlock(&engine->blender_gpu_context_mutex);
}
}
}
@ -1385,8 +1378,8 @@ void RE_engine_gpu_context_lock(RenderEngine *engine)
/* Locking already handled by the draw manager. */
}
else {
if (engine->wm_gpu_context) {
BLI_mutex_lock(&engine->gpu_context_mutex);
if (engine->wm_blender_gpu_context) {
BLI_mutex_lock(&engine->blender_gpu_context_mutex);
}
}
}
@ -1397,8 +1390,8 @@ void RE_engine_gpu_context_unlock(RenderEngine *engine)
/* Locking already handled by the draw manager. */
}
else {
if (engine->wm_gpu_context) {
BLI_mutex_unlock(&engine->gpu_context_mutex);
if (engine->wm_blender_gpu_context) {
BLI_mutex_unlock(&engine->blender_gpu_context_mutex);
}
}
}

View File

@ -877,44 +877,44 @@ void RE_test_break_cb(Render *re, void *handle, bool (*f)(void *handle))
/** \} */
/* -------------------------------------------------------------------- */
/** \name OpenGL Context
/** \name GPU Context
* \{ */
void RE_gl_context_create(Render *re)
void RE_system_gpu_context_create(Render *re)
{
/* Needs to be created in the main OpenGL thread. */
re->gl_context = WM_opengl_context_create();
/* Needs to be created in the main thread. */
re->system_gpu_context = WM_system_gpu_context_create();
/* So we activate the window's one afterwards. */
wm_window_reset_drawable();
}
void RE_gl_context_destroy(Render *re)
void RE_system_gpu_context_destroy(Render *re)
{
/* Needs to be called from the thread which used the OpenGL context for rendering. */
if (re->gl_context) {
if (re->gpu_context) {
WM_opengl_context_activate(re->gl_context);
GPU_context_active_set(static_cast<GPUContext *>(re->gpu_context));
GPU_context_discard(static_cast<GPUContext *>(re->gpu_context));
re->gpu_context = nullptr;
/* Needs to be called from the thread which used the GPU context for rendering. */
if (re->system_gpu_context) {
if (re->blender_gpu_context) {
WM_system_gpu_context_activate(re->system_gpu_context);
GPU_context_active_set(static_cast<GPUContext *>(re->blender_gpu_context));
GPU_context_discard(static_cast<GPUContext *>(re->blender_gpu_context));
re->blender_gpu_context = nullptr;
}
WM_opengl_context_dispose(re->gl_context);
re->gl_context = nullptr;
WM_system_gpu_context_dispose(re->system_gpu_context);
re->system_gpu_context = nullptr;
}
}
void *RE_gl_context_get(Render *re)
void *RE_system_gpu_context_get(Render *re)
{
return re->gl_context;
return re->system_gpu_context;
}
void *RE_gpu_context_get(Render *re)
void *RE_blender_gpu_context_get(Render *re)
{
if (re->gpu_context == nullptr) {
re->gpu_context = GPU_context_create(nullptr, re->gl_context);
if (re->blender_gpu_context == nullptr) {
re->blender_gpu_context = GPU_context_create(nullptr, re->system_gpu_context);
}
return re->gpu_context;
return re->blender_gpu_context;
}
/** \} */
@ -1752,7 +1752,7 @@ static void render_pipeline_free(Render *re)
re->pipeline_scene_eval = nullptr;
}
/* Destroy the opengl context in the correct thread. */
RE_gl_context_destroy(re);
RE_system_gpu_context_destroy(re);
/* In the case the engine did not mark tiles as finished (un-highlight, which could happen in the
* case of cancelled render) ensure the storage is empty. */

View File

@ -124,8 +124,8 @@ struct Render {
char viewname[MAX_NAME];
/* TODO: replace by a whole draw manager. */
void *gl_context;
void *gpu_context;
void *system_gpu_context;
void *blender_gpu_context;
};
/* **************** defines ********************* */

View File

@ -144,7 +144,7 @@ void WM_init_splash_on_startup(struct bContext *C);
*/
void WM_init_splash(struct bContext *C);
void WM_init_opengl(void);
void WM_init_gpu(void);
/**
* Return an identifier for the underlying GHOST implementation.
@ -313,10 +313,10 @@ void WM_window_ensure_active_view_layer(struct wmWindow *win) ATTR_NONNULL(1);
bool WM_window_is_temp_screen(const struct wmWindow *win) ATTR_WARN_UNUSED_RESULT;
void *WM_opengl_context_create(void);
void WM_opengl_context_dispose(void *context);
void WM_opengl_context_activate(void *context);
void WM_opengl_context_release(void *context);
void *WM_system_gpu_context_create(void);
void WM_system_gpu_context_dispose(void *context);
void WM_system_gpu_context_activate(void *context);
void WM_system_gpu_context_release(void *context);
/* #WM_window_open alignment */
typedef enum eWindowAlignment {

View File

@ -1199,11 +1199,11 @@ static void wm_draw_surface(bContext *C, wmSurface *surface)
wm_window_clear_drawable(CTX_wm_manager(C));
wm_surface_make_drawable(surface);
GPU_context_begin_frame(surface->gpu_ctx);
GPU_context_begin_frame(surface->blender_gpu_context);
surface->draw(C);
GPU_context_end_frame(surface->gpu_ctx);
GPU_context_end_frame(surface->blender_gpu_context);
/* Avoid interference with window drawable */
wm_surface_clear_drawable();

View File

@ -159,12 +159,12 @@ void WM_init_state_start_with_console_set(bool value)
* so that it does not break anything that can run in headless mode (as in
* without display server attached).
*/
static bool opengl_is_init = false;
static bool gpu_is_init = false;
void WM_init_opengl(void)
void WM_init_gpu(void)
{
/* Must be called only once. */
BLI_assert(opengl_is_init == false);
BLI_assert(gpu_is_init == false);
if (G.background) {
/* Ghost is still not initialized elsewhere in background mode. */
@ -176,13 +176,13 @@ void WM_init_opengl(void)
}
/* Needs to be first to have an OpenGL context bound. */
DRW_opengl_context_create();
DRW_gpu_context_create();
GPU_init();
GPU_pass_cache_init();
opengl_is_init = true;
gpu_is_init = true;
}
static void sound_jack_sync_callback(Main *bmain, int mode, double time)
@ -317,7 +317,7 @@ void WM_init(bContext *C, int argc, const char **argv)
/* Sets 3D mouse dead-zone. */
WM_ndof_deadzone_set(U.ndof_deadzone);
#endif
WM_init_opengl();
WM_init_gpu();
if (!WM_platform_support_perform_checks()) {
/* No attempt to avoid memory leaks here. */
@ -603,7 +603,7 @@ void WM_exit_ex(bContext *C, const bool do_python, const bool do_user_exit_actio
BKE_subdiv_exit();
if (opengl_is_init) {
if (gpu_is_init) {
BKE_image_free_unused_gpu_textures();
}
@ -617,7 +617,7 @@ void WM_exit_ex(bContext *C, const bool do_python, const bool do_user_exit_actio
/* Free the GPU subdivision data after the database to ensure that subdivision structs used by
* the modifiers were garbage collected. */
if (opengl_is_init) {
if (gpu_is_init) {
DRW_subdiv_free();
}
@ -664,13 +664,13 @@ void WM_exit_ex(bContext *C, const bool do_python, const bool do_user_exit_actio
/* Delete GPU resources and context. The UI also uses GPU resources and so
* is also deleted with the context active. */
if (opengl_is_init) {
DRW_opengl_context_enable_ex(false);
if (gpu_is_init) {
DRW_gpu_context_enable_ex(false);
UI_exit();
GPU_pass_cache_free();
GPU_exit();
DRW_opengl_context_disable_ex(false);
DRW_opengl_context_destroy();
DRW_gpu_context_disable_ex(false);
DRW_gpu_context_destroy();
}
else {
UI_exit();

Some files were not shown because too many files have changed in this diff Show More