From cdb8a8929cecd09735092e9ad1fc3adf15501615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Jul 2023 14:16:03 +0200 Subject: [PATCH] GHOST: Delete Mac OpenGL support The maximum OpenGL versions supported on mac doesn't meet the minimum required version (>=4.3) anymore. This removes all the OpenGL paths in GHOST Cocoa backend and from the drop down menu in the user preferences. Pull Request: https://projects.blender.org/blender/blender/pulls/110185 --- CMakeLists.txt | 8 +- intern/ghost/intern/GHOST_ContextCGL.hh | 20 +- intern/ghost/intern/GHOST_ContextCGL.mm | 623 ++---------------- intern/ghost/intern/GHOST_SystemCocoa.mm | 17 +- intern/ghost/intern/GHOST_WindowCocoa.mm | 49 +- scripts/startup/bl_ui/space_userpref.py | 22 - .../blenloader/intern/versioning_userdef.c | 7 + source/blender/gpu/intern/gpu_context.cc | 13 +- 8 files changed, 113 insertions(+), 646 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 113ec61655a..6612e939305 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -650,8 +650,12 @@ mark_as_advanced( ) # OpenGL -option(WITH_OPENGL_BACKEND "Enable OpenGL support as graphic backend" ON) -mark_as_advanced(WITH_OPENGL_BACKEND) +if(NOT APPLE) + option(WITH_OPENGL_BACKEND "Enable OpenGL support as graphic backend" ON) + mark_as_advanced(WITH_OPENGL_BACKEND) +else() + set(WITH_OPENGL_BACKEND OFF) +endif() # Vulkan option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (only for development)" OFF) diff --git a/intern/ghost/intern/GHOST_ContextCGL.hh b/intern/ghost/intern/GHOST_ContextCGL.hh index 50fd2c342bf..46f14c68f21 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.hh +++ b/intern/ghost/intern/GHOST_ContextCGL.hh @@ -44,11 +44,7 @@ class GHOST_ContextCGL : public GHOST_Context { /** * Constructor. */ - GHOST_ContextCGL(bool stereoVisual, - NSView *metalView, - CAMetalLayer *metalLayer, - NSOpenGLView *openglView, - GHOST_TDrawingContextType type); + GHOST_ContextCGL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, int debug); /** * Destructor. @@ -134,23 +130,11 @@ class GHOST_ContextCGL : public GHOST_Context { private: /** Metal state */ - /* Set this flag to `true` when rendering with Metal API for Viewport. - * TODO(Metal): This should be assigned to externally. */ - bool m_useMetalForRendering = false; NSView *m_metalView; CAMetalLayer *m_metalLayer; MTLRenderPipelineState *m_metalRenderPipeline; bool m_ownsMetalDevice; - /** OpenGL state, for GPUs that don't support Metal */ - NSOpenGLView *m_openGLView; - - /** The OpenGL drawing context */ - NSOpenGLContext *m_openGLContext; - - /** The virtualized default frame-buffer. */ - unsigned int m_defaultFramebuffer; - /** The virtualized default frame-buffer's texture. */ /** * Texture that you can render into with Metal. The texture will be @@ -191,5 +175,5 @@ class GHOST_ContextCGL : public GHOST_Context { void metalInitFramebuffer(); void metalUpdateFramebuffer(); void metalSwapBuffers(); - void initClear(); + void initClear(){}; }; diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 2a4e6eb6d47..a13bf7e3f28 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -27,9 +27,7 @@ static void ghost_fatal_error_dialog(const char *msg) { - /* clang-format off */ @autoreleasepool { - /* clang-format on */ NSString *message = [NSString stringWithFormat:@"Error opening window:\n%s", msg]; NSAlert *alert = [[NSAlert alloc] init]; @@ -50,17 +48,12 @@ int GHOST_ContextCGL::s_sharedCount = 0; GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, - NSOpenGLView *openGLView, - GHOST_TDrawingContextType type) + int debug) : GHOST_Context(stereoVisual), - m_useMetalForRendering(type == GHOST_kDrawingContextTypeMetal), m_metalView(metalView), m_metalLayer(metalLayer), m_metalRenderPipeline(nil), - m_openGLView(openGLView), - m_openGLContext(nil), - m_defaultFramebuffer(0), - m_debug(false) + m_debug(debug) { /* Initialize Metal Swap-chain. */ current_swapchain_index = 0; @@ -68,6 +61,7 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual, m_defaultFramebufferMetalTexture[i].texture = nil; m_defaultFramebufferMetalTexture[i].index = i; } + if (m_metalView) { m_ownsMetalDevice = false; metalInit(); @@ -107,31 +101,6 @@ GHOST_ContextCGL::~GHOST_ContextCGL() { metalFree(); - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - if (m_openGLContext != nil) { - if (m_openGLContext == [NSOpenGLContext currentContext]) { - [NSOpenGLContext clearCurrentContext]; - - if (m_openGLView) { - [m_openGLView clearGLContext]; - } - } - - if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) { - assert(s_sharedCount > 0); - - s_sharedCount--; - - if (s_sharedCount == 0) - s_sharedOpenGLContext = nil; - - [m_openGLContext release]; - } - } -#endif - } - if (m_ownsMetalDevice) { if (m_metalLayer) { [m_metalLayer release]; @@ -142,165 +111,45 @@ GHOST_ContextCGL::~GHOST_ContextCGL() GHOST_TSuccess GHOST_ContextCGL::swapBuffers() { - GHOST_TSuccess return_value = GHOST_kFailure; - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - if (m_openGLContext != nil) { - if (m_metalView) { - metalSwapBuffers(); - } - else if (m_openGLView) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [m_openGLContext flushBuffer]; - [pool drain]; - } - return_value = GHOST_kSuccess; - } - else { - return_value = GHOST_kFailure; - } -#endif + if (m_metalView) { + metalSwapBuffers(); } - else { - if (m_metalView) { - metalSwapBuffers(); - } - return_value = GHOST_kSuccess; - } - return return_value; + return GHOST_kSuccess; } GHOST_TSuccess GHOST_ContextCGL::setSwapInterval(int interval) { - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - if (m_openGLContext != nil) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [m_openGLContext setValues:&interval forParameter:NSOpenGLCPSwapInterval]; - [pool drain]; - return GHOST_kSuccess; - } - else { - return GHOST_kFailure; - } -#endif - } - else { - mtl_SwapInterval = interval; - return GHOST_kSuccess; - } + mtl_SwapInterval = interval; + return GHOST_kSuccess; } GHOST_TSuccess GHOST_ContextCGL::getSwapInterval(int &intervalOut) { - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - if (m_openGLContext != nil) { - GLint interval; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - [m_openGLContext getValues:&interval forParameter:NSOpenGLCPSwapInterval]; - - [pool drain]; - - intervalOut = static_cast(interval); - - return GHOST_kSuccess; - } - else { - return GHOST_kFailure; - } -#endif - } - else { - intervalOut = mtl_SwapInterval; - return GHOST_kSuccess; - } + intervalOut = mtl_SwapInterval; + return GHOST_kSuccess; } GHOST_TSuccess GHOST_ContextCGL::activateDrawingContext() { - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - if (m_openGLContext != nil) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [m_openGLContext makeCurrentContext]; - [pool drain]; - return GHOST_kSuccess; - } - else { - return GHOST_kFailure; - } -#endif - } - else { - return GHOST_kSuccess; - } + return GHOST_kSuccess; } GHOST_TSuccess GHOST_ContextCGL::releaseDrawingContext() { - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - if (m_openGLContext != nil) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [NSOpenGLContext clearCurrentContext]; - [pool drain]; - return GHOST_kSuccess; - } - else { - return GHOST_kFailure; - } -#endif - } - else { - return GHOST_kSuccess; - } + return GHOST_kSuccess; } unsigned int GHOST_ContextCGL::getDefaultFramebuffer() { - - if (!m_useMetalForRendering) { - return m_defaultFramebuffer; - } /* NOTE(Metal): This is not valid. */ return 0; } GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext() { - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - if (m_openGLContext != nil) { - if (m_metalView) { - metalUpdateFramebuffer(); - } - else if (m_openGLView) { - @autoreleasepool { - [m_openGLContext update]; - } - } - - return GHOST_kSuccess; - } - else { - return GHOST_kFailure; - } -#endif - } - else { - if (m_metalView) { - metalUpdateFramebuffer(); - return GHOST_kSuccess; - } + if (m_metalView) { + metalUpdateFramebuffer(); + return GHOST_kSuccess; } return GHOST_kFailure; } @@ -333,174 +182,11 @@ void GHOST_ContextCGL::metalRegisterPresentCallback(void (*callback)( this->contextPresentCallback = callback; } -static void makeAttribList(std::vector &attribs, - bool stereoVisual, - bool needAlpha, - bool softwareGL, - bool increasedSamplerLimit) -{ - attribs.clear(); - - attribs.push_back(NSOpenGLPFAOpenGLProfile); - attribs.push_back(NSOpenGLProfileVersion3_2Core); - - /* Pixel Format Attributes for the windowed #NSOpenGLContext. */ - attribs.push_back(NSOpenGLPFADoubleBuffer); - - if (softwareGL) { - attribs.push_back(NSOpenGLPFARendererID); - attribs.push_back(kCGLRendererGenericFloatID); - } - else { - attribs.push_back(NSOpenGLPFAAccelerated); - attribs.push_back(NSOpenGLPFANoRecovery); - - /* Attempt to initialize device with extended sampler limit. - * Resolves EEVEE purple rendering artifacts on macOS. */ - if (increasedSamplerLimit) { - attribs.push_back((NSOpenGLPixelFormatAttribute)400); - } - } - - if (stereoVisual) - attribs.push_back(NSOpenGLPFAStereo); - - if (needAlpha) { - attribs.push_back(NSOpenGLPFAAlphaSize); - attribs.push_back((NSOpenGLPixelFormatAttribute)8); - } - - attribs.push_back((NSOpenGLPixelFormatAttribute)0); -} - GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext() { @autoreleasepool { - -#ifdef GHOST_OPENGL_ALPHA - static const bool needAlpha = true; -#else - static const bool needAlpha = false; -#endif - - /* Command-line argument would be better. */ - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - /* Command-line argument would be better. */ - static bool softwareGL = getenv("BLENDER_SOFTWAREGL"); - - NSOpenGLPixelFormat *pixelFormat = nil; - std::vector attribs; - bool increasedSamplerLimit = false; - - /* Attempt to initialize device with increased sampler limit. - * If this is unsupported and initialization fails, initialize GL Context as normal. - * - * NOTE: This is not available when using the SoftwareGL path, or for Intel-based - * platforms. */ - if (!softwareGL) { - if (@available(macos 11.0, *)) { - increasedSamplerLimit = true; - } - } - const int max_ctx_attempts = increasedSamplerLimit ? 2 : 1; - for (int ctx_create_attempt = 0; ctx_create_attempt < max_ctx_attempts; ctx_create_attempt++) - { - - attribs.clear(); - attribs.reserve(40); - makeAttribList(attribs, m_stereoVisual, needAlpha, softwareGL, increasedSamplerLimit); - - pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]]; - if (pixelFormat == nil) { - /* If pixel format creation fails when testing increased sampler limit, - * attempt initialization again with feature disabled, otherwise, fail. */ - if (increasedSamplerLimit) { - increasedSamplerLimit = false; - continue; - } - return GHOST_kFailure; - } - - /* Attempt to create context. */ - m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat - shareContext:s_sharedOpenGLContext]; - [pixelFormat release]; - - if (m_openGLContext == nil) { - /* If context creation fails when testing increased sampler limit, - * attempt re-creation with feature disabled. Otherwise, error. */ - if (increasedSamplerLimit) { - increasedSamplerLimit = false; - continue; - } - - /* Default context creation attempt failed. */ - return GHOST_kFailure; - } - - /* Created GL context successfully, activate. */ - [m_openGLContext makeCurrentContext]; - - /* When increasing sampler limit, verify created context is a supported configuration. */ - if (increasedSamplerLimit) { - const char *vendor = (const char *)glGetString(GL_VENDOR); - const char *renderer = (const char *)glGetString(GL_RENDERER); - - /* If generated context type is unsupported, release existing context and - * fallback to creating a normal context below. */ - if (strstr(vendor, "Intel") || strstr(renderer, "Software")) { - [m_openGLContext release]; - m_openGLContext = nil; - increasedSamplerLimit = false; - continue; - } - } - } - - if (m_debug) { - GLint major = 0, minor = 0; - glGetIntegerv(GL_MAJOR_VERSION, &major); - glGetIntegerv(GL_MINOR_VERSION, &minor); - fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : ""); - fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER)); - } - -# ifdef GHOST_WAIT_FOR_VSYNC - { - GLint swapInt = 1; - /* Wait for vertical-sync, to avoid tearing artifacts. */ - [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; - } -# endif - - if (m_metalView) { - if (m_defaultFramebuffer == 0) { - /* Create a virtual frame-buffer. */ - [m_openGLContext makeCurrentContext]; - metalInitFramebuffer(); - initClearGL(); - } - } - else if (m_openGLView) { - [m_openGLView setOpenGLContext:m_openGLContext]; - [m_openGLContext setView:m_openGLView]; - initClearGL(); - } - - [m_openGLContext flushBuffer]; - - if (s_sharedCount == 0) - s_sharedOpenGLContext = m_openGLContext; - - s_sharedCount++; -#endif - } - else { - /* NOTE(Metal): Metal-only path. */ - if (m_metalView) { - metalInitFramebuffer(); - } + if (m_metalView) { + metalInitFramebuffer(); } } return GHOST_kSuccess; @@ -508,27 +194,16 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext() GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles() { -#ifdef WITH_OPENGL_BACKEND - m_openGLContext = nil; - m_openGLView = nil; -#endif m_metalView = nil; return GHOST_kSuccess; } -/* OpenGL on Metal - * - * Use Metal layer to avoid Viewport lagging on macOS, see #60043. */ - static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatBGRA8Unorm; -static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT = kCVPixelFormatType_32BGRA; void GHOST_ContextCGL::metalInit() { - /* clang-format off */ @autoreleasepool { - /* clang-format on */ id device = m_metalLayer.device; /* Create a command queue for blit/present operation. Note: All context should share a single @@ -634,213 +309,75 @@ void GHOST_ContextCGL::metalFree() void GHOST_ContextCGL::metalInitFramebuffer() { - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - glGenFramebuffers(1, &m_defaultFramebuffer); -#endif - } updateDrawingContext(); - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer); -#endif - } } void GHOST_ContextCGL::metalUpdateFramebuffer() { - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - assert(m_defaultFramebuffer != 0); -#endif - } - NSRect bounds = [m_metalView bounds]; NSSize backingSize = [m_metalView convertSizeToBacking:bounds.size]; size_t width = (size_t)backingSize.width; size_t height = (size_t)backingSize.height; -#ifdef WITH_OPENGL_BACKEND - unsigned int glTex; - CVPixelBufferRef cvPixelBuffer = nil; - CVOpenGLTextureCacheRef cvGLTexCache = nil; - CVOpenGLTextureRef cvGLTex = nil; - CVMetalTextureCacheRef cvMetalTexCache = nil; - CVMetalTextureRef cvMetalTex = nil; -#endif + if (m_defaultFramebufferMetalTexture[current_swapchain_index].texture && + m_defaultFramebufferMetalTexture[current_swapchain_index].texture.width == width && + m_defaultFramebufferMetalTexture[current_swapchain_index].texture.height == height) + { + return; + } - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - /* OPENGL path */ - { - /* Test if there is anything to update */ - id tex = m_defaultFramebufferMetalTexture[current_swapchain_index].texture; - if (tex && tex.width == width && tex.height == height) { - return; - } - } + /* Free old texture */ + [m_defaultFramebufferMetalTexture[current_swapchain_index].texture release]; - activateDrawingContext(); + id device = m_metalLayer.device; + MTLTextureDescriptor *overlayDesc = [MTLTextureDescriptor + texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA16Float + width:width + height:height + mipmapped:NO]; + overlayDesc.storageMode = MTLStorageModePrivate; + overlayDesc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - NSDictionary *cvPixelBufferProps = @{ - (__bridge NSString *)kCVPixelBufferOpenGLCompatibilityKey : @YES, - (__bridge NSString *)kCVPixelBufferMetalCompatibilityKey : @YES, - }; - CVReturn cvret = CVPixelBufferCreate(kCFAllocatorDefault, - width, - height, - METAL_CORE_VIDEO_PIXEL_FORMAT, - (__bridge CFDictionaryRef)cvPixelBufferProps, - &cvPixelBuffer); - if (cvret != kCVReturnSuccess) { - ghost_fatal_error_dialog( - "GHOST_ContextCGL::metalUpdateFramebuffer: CVPixelBufferCreate failed!"); - } - - /* Create an OpenGL texture. */ - cvret = CVOpenGLTextureCacheCreate(kCFAllocatorDefault, - nil, - m_openGLContext.CGLContextObj, - m_openGLContext.pixelFormat.CGLPixelFormatObj, - nil, - &cvGLTexCache); - if (cvret != kCVReturnSuccess) { - ghost_fatal_error_dialog( - "GHOST_ContextCGL::metalUpdateFramebuffer: CVOpenGLTextureCacheCreate failed!"); - } - - cvret = CVOpenGLTextureCacheCreateTextureFromImage( - kCFAllocatorDefault, cvGLTexCache, cvPixelBuffer, nil, &cvGLTex); - if (cvret != kCVReturnSuccess) { - ghost_fatal_error_dialog( - "GHOST_ContextCGL::metalUpdateFramebuffer: " - "CVOpenGLTextureCacheCreateTextureFromImage failed!"); - } - - glTex = CVOpenGLTextureGetName(cvGLTex); - - /* Create a Metal texture. */ - cvret = CVMetalTextureCacheCreate( - kCFAllocatorDefault, nil, m_metalLayer.device, nil, &cvMetalTexCache); - if (cvret != kCVReturnSuccess) { - ghost_fatal_error_dialog( - "GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureCacheCreate failed!"); - } - - cvret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, - cvMetalTexCache, - cvPixelBuffer, - nil, - METAL_FRAMEBUFFERPIXEL_FORMAT, - width, - height, - 0, - &cvMetalTex); - if (cvret != kCVReturnSuccess) { - ghost_fatal_error_dialog( - "GHOST_ContextCGL::metalUpdateFramebuffer: " - "CVMetalTextureCacheCreateTextureFromImage failed!"); - } - - id tex = CVMetalTextureGetTexture(cvMetalTex); - - if (!tex) { - ghost_fatal_error_dialog( - "GHOST_ContextCGL::metalUpdateFramebuffer: CVMetalTextureGetTexture failed!"); - } - - [m_defaultFramebufferMetalTexture[current_swapchain_index].texture release]; - m_defaultFramebufferMetalTexture[current_swapchain_index].texture = [tex retain]; -#endif + id overlayTex = [device newTextureWithDescriptor:overlayDesc]; + if (!overlayTex) { + ghost_fatal_error_dialog( + "GHOST_ContextCGL::metalUpdateFramebuffer: failed to create Metal overlay texture!"); } else { - /* NOTE(Metal): Metal API Path. */ - if (m_defaultFramebufferMetalTexture[current_swapchain_index].texture && - m_defaultFramebufferMetalTexture[current_swapchain_index].texture.width == width && - m_defaultFramebufferMetalTexture[current_swapchain_index].texture.height == height) - { - return; - } + overlayTex.label = [NSString + stringWithFormat:@"Metal Overlay for GHOST Context %p", this]; //@""; - /* Free old texture */ - [m_defaultFramebufferMetalTexture[current_swapchain_index].texture release]; - - id device = m_metalLayer.device; - MTLTextureDescriptor *overlayDesc = [MTLTextureDescriptor - texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA16Float - width:width - height:height - mipmapped:NO]; - overlayDesc.storageMode = MTLStorageModePrivate; - overlayDesc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - - id overlayTex = [device newTextureWithDescriptor:overlayDesc]; - if (!overlayTex) { - ghost_fatal_error_dialog( - "GHOST_ContextCGL::metalUpdateFramebuffer: failed to create Metal overlay texture!"); - } - else { - overlayTex.label = [NSString - stringWithFormat:@"Metal Overlay for GHOST Context %p", this]; //@""; - - // NSLog(@"Created new Metal Overlay (backbuffer) for context %p\n", this); - } - - m_defaultFramebufferMetalTexture[current_swapchain_index].texture = - overlayTex; //[(MTLTexture *)overlayTex retain]; - - /* Clear texture on create */ - id cmdBuffer = [s_sharedMetalCommandQueue commandBuffer]; - MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; - { - auto attachment = [passDescriptor.colorAttachments objectAtIndexedSubscript:0]; - attachment.texture = m_defaultFramebufferMetalTexture[current_swapchain_index].texture; - attachment.loadAction = MTLLoadActionClear; - attachment.clearColor = MTLClearColorMake(0.294, 0.294, 0.294, 1.000); - attachment.storeAction = MTLStoreActionStore; - } - { - id enc = [cmdBuffer - renderCommandEncoderWithDescriptor:passDescriptor]; - [enc endEncoding]; - } - [cmdBuffer commit]; + // NSLog(@"Created new Metal Overlay (backbuffer) for context %p\n", this); } - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - glBindFramebuffer(GL_FRAMEBUFFER, m_defaultFramebuffer); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, glTex, 0); -#endif + m_defaultFramebufferMetalTexture[current_swapchain_index].texture = + overlayTex; //[(MTLTexture *)overlayTex retain]; + + /* Clear texture on create */ + id cmdBuffer = [s_sharedMetalCommandQueue commandBuffer]; + MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; + { + auto attachment = [passDescriptor.colorAttachments objectAtIndexedSubscript:0]; + attachment.texture = m_defaultFramebufferMetalTexture[current_swapchain_index].texture; + attachment.loadAction = MTLLoadActionClear; + attachment.clearColor = MTLClearColorMake(0.294, 0.294, 0.294, 1.000); + attachment.storeAction = MTLStoreActionStore; } + { + id enc = [cmdBuffer + renderCommandEncoderWithDescriptor:passDescriptor]; + [enc endEncoding]; + } + [cmdBuffer commit]; [m_metalLayer setDrawableSize:CGSizeMake((CGFloat)width, (CGFloat)height)]; - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - CVPixelBufferRelease(cvPixelBuffer); - CVOpenGLTextureCacheRelease(cvGLTexCache); - CVOpenGLTextureRelease(cvGLTex); - CFRelease(cvMetalTexCache); - CFRelease(cvMetalTex); -#endif - } } void GHOST_ContextCGL::metalSwapBuffers() { - /* clang-format off */ @autoreleasepool { - /* clang-format on */ updateDrawingContext(); - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - glFlush(); - assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil); -#endif - } - id drawable = [m_metalLayer nextDrawable]; if (!drawable) { return; @@ -855,43 +392,11 @@ void GHOST_ContextCGL::metalSwapBuffers() attachment.storeAction = MTLStoreActionStore; } - if (!m_useMetalForRendering) { - id cmdBuffer = [s_sharedMetalCommandQueue commandBuffer]; - { - assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil); - id enc = [cmdBuffer - renderCommandEncoderWithDescriptor:passDescriptor]; - [enc setRenderPipelineState:(id)m_metalRenderPipeline]; - [enc setFragmentTexture:m_defaultFramebufferMetalTexture[current_swapchain_index].texture - atIndex:0]; - [enc drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3]; - [enc endEncoding]; - } - - [cmdBuffer presentDrawable:drawable]; - - /* Submit command buffer */ - [cmdBuffer commit]; - } - else { - assert(contextPresentCallback); - assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil); - (*contextPresentCallback)(passDescriptor, - (id)m_metalRenderPipeline, - m_defaultFramebufferMetalTexture[current_swapchain_index].texture, - drawable); - } - } -} - -void GHOST_ContextCGL::initClear() -{ - - if (!m_useMetalForRendering) { -#ifdef WITH_OPENGL_BACKEND - glClearColor(0.294, 0.294, 0.294, 0.000); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0.000, 0.000, 0.000, 0.000); -#endif + assert(contextPresentCallback); + assert(m_defaultFramebufferMetalTexture[current_swapchain_index].texture != nil); + (*contextPresentCallback)(passDescriptor, + (id)m_metalRenderPipeline, + m_defaultFramebufferMetalTexture[current_swapchain_index].texture, + drawable); } } diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index ac3bd77c602..a77e1882408 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -23,7 +23,7 @@ # pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#if defined(WITH_OPENGL_BACKEND) || defined(WITH_METAL_BACKEND) +#ifdef WITH_METAL_BACKEND # include "GHOST_ContextCGL.hh" #endif @@ -763,10 +763,11 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, */ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings) { + const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0; + switch (gpuSettings.context_type) { #ifdef WITH_VULKAN_BACKEND case 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()) { return context; @@ -775,17 +776,11 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuS return nullptr; } #endif -#ifdef WITH_OPENGL_BACKEND - case GHOST_kDrawingContextTypeOpenGL: -#endif + #ifdef WITH_METAL_BACKEND - case GHOST_kDrawingContextTypeMetal: -#endif -#if defined(WITH_OPENGL_BACKEND) || defined(WITH_METAL_BACKEND) - { + case GHOST_kDrawingContextTypeMetal: { /* TODO(fclem): Remove OpenGL support and rename context to ContextMTL */ - GHOST_Context *context = new GHOST_ContextCGL( - false, NULL, NULL, NULL, gpuSettings.context_type); + GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, debug_context); if (context->initializeDrawingContext()) { return context; } diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 5d743a3e3f5..8e4f3b1fd6e 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -13,7 +13,9 @@ # pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#include "GHOST_ContextCGL.hh" +#ifdef WITH_METAL_BACKEND +# include "GHOST_ContextCGL.hh" +#endif #ifdef WITH_VULKAN_BACKEND # include "GHOST_ContextVK.hh" @@ -816,37 +818,34 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type) { + switch (type) { #ifdef WITH_VULKAN_BACKEND - if (type == GHOST_kDrawingContextTypeVulkan) { - GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual, m_metalLayer, 1, 2, true); - - if (!context->initializeDrawingContext()) { + case GHOST_kDrawingContextTypeVulkan: { + GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual, m_metalLayer, 1, 2, true); + if (context->initializeDrawingContext()) { + return context; + } delete context; - return NULL; + return nullptr; } - - return context; - } #endif - if (true -#if defined(WITH_OPENGL_BACKEND) - || type == GHOST_kDrawingContextTypeOpenGL -#elif defined(WITH_METAL_BACKEND) - || type == GHOST_kDrawingContextTypeMetal -#endif - ) - { - GHOST_Context *context = new GHOST_ContextCGL( - m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView, type); - - if (context->initializeDrawingContext()) - return context; - else +#ifdef WITH_METAL_BACKEND + case GHOST_kDrawingContextTypeMetal: { + GHOST_Context *context = new GHOST_ContextCGL( + m_wantStereoVisual, m_metalView, m_metalLayer, false); + if (context->initializeDrawingContext()) { + return context; + } delete context; - } + return nullptr; + } +#endif - return NULL; + default: + /* Unsupported backend. */ + return nullptr; + } } #pragma mark invalidate diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index 81330ec7cbf..9b5c16569da 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -611,27 +611,6 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel): del addon -class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel): - bl_label = "GPU Backend" - - @classmethod - def poll(cls, _context): - # Only for Apple so far - import sys - return sys.platform == "darwin" - - def draw_centered(self, context, layout): - import gpu - prefs = context.preferences - system = prefs.system - - col = layout.column() - col.prop(system, "gpu_backend") - - if system.gpu_backend != gpu.platform.backend_type_get(): - layout.label(text="Requires a restart of Blender to take effect", icon='INFO') - - class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel): bl_label = "Operating System Settings" @@ -2525,7 +2504,6 @@ classes = ( USERPREF_PT_animation_fcurves, USERPREF_PT_system_cycles_devices, - USERPREF_PT_system_gpu_backend, USERPREF_PT_system_os_settings, USERPREF_PT_system_memory, USERPREF_PT_system_video_sequencer, diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index fbe7e92ca17..90836a5a1d3 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -845,6 +845,13 @@ void blo_do_versions_userdef(UserDef *userdef) */ { /* Keep this block, even when empty. */ + +#ifdef __APPLE__ + /* Drop OpenGL support on MAC devices as they don't support OpenGL 4.3. */ + if (userdef->gpu_backend == GPU_BACKEND_OPENGL) { + userdef->gpu_backend = GPU_BACKEND_METAL; + } +#endif } LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) { diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index a3c39d61a19..fe88e8e30f6 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -219,9 +219,6 @@ void GPU_render_step() /** \name Backend selection * \{ */ -/* NOTE: To enable Metal API, we need to temporarily change this to `GPU_BACKEND_METAL`. - * Until a global switch is added, Metal also needs to be enabled in GHOST_ContextCGL: - * `m_useMetalForRendering = true`. */ static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; static std::optional g_backend_type_override = std::nullopt; static std::optional g_backend_type_supported = std::nullopt; @@ -255,13 +252,11 @@ bool GPU_backend_type_selection_detect() backends_to_check.append(*g_backend_type_override); } else { +#if defined(WITH_OPENGL_BACKEND) backends_to_check.append(GPU_BACKEND_OPENGL); - } - - /* Add fallback to OpenGL when Metal backend is requested on a platform that doesn't support - * metal. */ - if (backends_to_check[0] == GPU_BACKEND_METAL) { - backends_to_check.append(GPU_BACKEND_OPENGL); +#elif defined(WITH_METAL_BACKEND) + backends_to_check.append(GPU_BACKEND_METAL); +#endif } for (const eGPUBackendType backend_type : backends_to_check) {