Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/analyze-project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ jobs:
: Set Up Environment 🔧
if (( ${+RUNNER_DEBUG} )) setopt XTRACE

print '::group::Enable Xcode 16.1'
sudo xcode-select --switch /Applications/Xcode_16.1.0.app/Contents/Developer
print '::group::Enable Xcode 16.4'
sudo xcode-select --switch /Applications/Xcode_16.4.app/Contents/Developer
Comment thread
RytoEX marked this conversation as resolved.
print '::endgroup::'

print '::group::Clean Homebrew Environment'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ jobs:
: Set Up Environment 🔧
if (( ${+RUNNER_DEBUG} )) setopt XTRACE

print '::group::Enable Xcode 16.1'
sudo xcode-select --switch /Applications/Xcode_16.1.0.app/Contents/Developer
print '::group::Enable Xcode 16.4'
sudo xcode-select --switch /Applications/Xcode_16.4.app/Contents/Developer
Comment thread
RytoEX marked this conversation as resolved.
print '::endgroup::'

print '::group::Clean Homebrew Environment'
Expand Down
13 changes: 12 additions & 1 deletion .swift-format
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,16 @@
"maximumBlankLines": 1,
"respectsExistingLineBreaks": true,
"lineBreakBeforeControlFlowKeywords": false,
"lineBreakBeforeEachArgument": false
"lineBreakBeforeEachArgument": false,
"lineBreakBeforeEachGenericRequirement": false,
"lineBreakBetweenDeclarationAttributes": false,
"prioritizeKeepingFunctionOutputTogether": false,
"indentConditionalCompilationBlocks": true,
"lineBreakAroundMultilineExpressionChainComponents": false,
"fileScopedDeclarationPrivacy": {"accessLevel": "private"},
"indentSwitchCaseLabels": false,
"spacesAroundRangeFormationOperators": false,
"noAssignmentInExpressions": { "allowedFunctions" : ["XCTAssertNoThrow"] },
"multiElementCollectionTrailingCommas": true,
"indentBlankLines": false,
}
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ if(OS_WINDOWS)
add_subdirectory(libobs-winrt)
endif()
add_subdirectory(libobs-opengl)
if(OS_MACOS)
add_subdirectory(libobs-metal)
endif()
add_subdirectory(plugins)

add_subdirectory(test/test-input)
Expand Down
2 changes: 1 addition & 1 deletion cmake/macos/compilerconfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ string(APPEND CMAKE_OBJCXX_FLAGS_RELEASE " -g")
# * -Wno-non-virtual-dtor

add_compile_definitions(
$<$<NOT:$<COMPILE_LANGUAGE:Swift>>:$<$<CONFIG:DEBUG>:DEBUG>>
$<$<CONFIG:DEBUG>:DEBUG>
$<$<NOT:$<COMPILE_LANGUAGE:Swift>>:$<$<CONFIG:DEBUG>:_DEBUG>>
$<$<NOT:$<COMPILE_LANGUAGE:Swift>>:SIMDE_ENABLE_OPENMP>
)
Expand Down
13 changes: 13 additions & 0 deletions frontend/OBSApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,14 @@ bool OBSApp::InitGlobalConfigDefaults()

#if _WIN32
config_set_default_string(appConfig, "Video", "Renderer", "Direct3D 11");
#else
#if defined(__APPLE__) && defined(__aarch64__)
// TODO: Change this value to "Metal" once the renderer has reached production quality
config_set_default_string(appConfig, "Video", "Renderer", "OpenGL");
#else
config_set_default_string(appConfig, "Video", "Renderer", "OpenGL");
#endif
#endif

#ifdef _WIN32
config_set_default_bool(appConfig, "Audio", "DisableAudioDucking", true);
Expand Down Expand Up @@ -1077,9 +1082,17 @@ void OBSApp::checkForUncleanShutdown()

const char *OBSApp::GetRenderModule() const
{
#if defined(_WIN32)
const char *renderer = config_get_string(appConfig, "Video", "Renderer");

return (astrcmpi(renderer, "Direct3D 11") == 0) ? DL_D3D11 : DL_OPENGL;
#elif defined(__APPLE__) && defined(__aarch64__)
const char *renderer = config_get_string(appConfig, "Video", "Renderer");

return (astrcmpi(renderer, "Metal (Experimental)") == 0) ? DL_METAL : DL_OPENGL;
Comment thread
RytoEX marked this conversation as resolved.
#else
return DL_OPENGL;
#endif
}

static bool StartupOBS(const char *locale, profiler_name_store_t *store)
Expand Down
45 changes: 31 additions & 14 deletions frontend/settings/OBSBasicSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -608,11 +608,24 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
for (ProcessPriority pri : processPriorities)
ui->processPriority->addItem(QTStr(pri.name), pri.val);

#else
#if defined(__APPLE__) && defined(__aarch64__)
delete ui->adapterLabel;
delete ui->adapter;

ui->adapterLabel = nullptr;
ui->adapter = nullptr;
#else
delete ui->rendererLabel;
delete ui->renderer;
delete ui->adapterLabel;
delete ui->adapter;

ui->rendererLabel = nullptr;
ui->renderer = nullptr;
ui->adapterLabel = nullptr;
ui->adapter = nullptr;
#endif
delete ui->processPriorityLabel;
delete ui->processPriority;
delete ui->enableNewSocketLoop;
Expand All @@ -624,10 +637,6 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
#endif
delete ui->disableAudioDucking;

ui->rendererLabel = nullptr;
ui->renderer = nullptr;
ui->adapterLabel = nullptr;
ui->adapter = nullptr;
ui->processPriorityLabel = nullptr;
ui->processPriority = nullptr;
ui->enableNewSocketLoop = nullptr;
Expand Down Expand Up @@ -1384,16 +1393,21 @@ void OBSBasicSettings::LoadGeneralSettings()

void OBSBasicSettings::LoadRendererList()
{
#ifdef _WIN32
#if defined(_WIN32) || (defined(__APPLE__) && defined(__aarch64__))
const char *renderer = config_get_string(App()->GetAppConfig(), "Video", "Renderer");

#ifdef _WIN32
ui->renderer->addItem(QT_UTF8("Direct3D 11"));
if (opt_allow_opengl || strcmp(renderer, "OpenGL") == 0)
if (opt_allow_opengl || strcmp(renderer, "OpenGL") == 0) {
ui->renderer->addItem(QT_UTF8("OpenGL"));

int idx = ui->renderer->findText(QT_UTF8(renderer));
if (idx == -1)
idx = 0;
}
#else
ui->renderer->addItem(QT_UTF8("OpenGL"));
ui->renderer->addItem(QT_UTF8("Metal (Experimental)"));
#endif
int index = ui->renderer->findText(QT_UTF8(renderer));
if (index == -1) {
index = 0;
}

// the video adapter selection is not currently implemented, hide for now
// to avoid user confusion. was previously protected by
Expand All @@ -1403,7 +1417,7 @@ void OBSBasicSettings::LoadRendererList()
ui->adapter = nullptr;
ui->adapterLabel = nullptr;

ui->renderer->setCurrentIndex(idx);
ui->renderer->setCurrentIndex(index);
#endif
}

Expand Down Expand Up @@ -3130,10 +3144,13 @@ void OBSBasicSettings::SaveAdvancedSettings()
{
QString lastMonitoringDevice = config_get_string(main->Config(), "Audio", "MonitoringDeviceId");

#ifdef _WIN32
if (WidgetChanged(ui->renderer))
#if defined(_WIN32) || (defined(__APPLE__) && defined(__aarch64__))
if (WidgetChanged(ui->renderer)) {
config_set_string(App()->GetAppConfig(), "Video", "Renderer", QT_TO_UTF8(ui->renderer->currentText()));
}
#endif

#ifdef _WIN32
std::string priority = QT_TO_UTF8(ui->processPriority->currentData().toString());
config_set_string(App()->GetAppConfig(), "General", "ProcessPriority", priority.c_str());
if (main->Active())
Expand Down
70 changes: 70 additions & 0 deletions libobs-metal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
cmake_minimum_required(VERSION 3.28...3.30)

add_library(libobs-metal SHARED)
add_library(OBS::libobs-metal ALIAS libobs-metal)

target_sources(
libobs-metal
PRIVATE
CVPixelFormat+Extensions.swift
MTLCullMode+Extensions.swift
MTLOrigin+Extensions.swift
MTLPixelFormat+Extensions.swift
MTLRegion+Extensions.swift
MTLSize+Extensions.swift
MTLTexture+Extensions.swift
MTLTextureDescriptor+Extensions.swift
MTLTextureType+Extensions.swift
MTLViewport+Extensions.swift
MetalBuffer.swift
MetalDevice.swift
MetalError.swift
MetalRenderState.swift
MetalShader+Extensions.swift
MetalShader.swift
MetalStageBuffer.swift
MetalTexture.swift
OBSShader.swift
OBSSwapChain.swift
Sequence+Hashable.swift
libobs+Extensions.swift
libobs+SignalHandlers.swift
libobs-metal-Bridging-Header.h
metal-indexbuffer.swift
metal-samplerstate.swift
metal-shader.swift
metal-stagesurf.swift
metal-subsystem.swift
metal-swapchain.swift
metal-texture2d.swift
metal-texture3d.swift
metal-unimplemented.swift
metal-vertexbuffer.swift
metal-zstencilbuffer.swift
)

target_link_libraries(libobs-metal PRIVATE OBS::libobs)

target_enable_feature(libobs "Metal renderer")

set_property(SOURCE OBSMetalRenderer.swift APPEND PROPERTY COMPILE_FLAGS -emit-objc-header)

set_target_properties_obs(
libobs-metal
PROPERTIES FOLDER core
VERSION 0
PREFIX ""
)

set_target_xcode_properties(
libobs-metal
PROPERTIES SWIFT_VERSION 6.0
CLANG_ENABLE_OBJC_ARC YES
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION YES
GCC_WARN_SHADOW YES
CLANG_ENABLE_MODULES YES
CLANG_MODULES_AUTOLINK YES
GCC_STRICT_ALIASING YES
DEFINES_MODULE YES
SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/libobs-metal-Bridging-Header.h"
)
51 changes: 51 additions & 0 deletions libobs-metal/CVPixelFormat+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/******************************************************************************
Copyright (C) 2024 by Patrick Heyer <PatTheMav@users.noreply.github.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

import CoreVideo
import Metal

extension OSType {
/// Conversion of CoreVideo pixel formats into corresponding Metal pixel formats
var mtlFormat: MTLPixelFormat? {
switch self {
case kCVPixelFormatType_OneComponent8:
return .r8Unorm
case kCVPixelFormatType_OneComponent16Half:
return .r16Float
case kCVPixelFormatType_OneComponent32Float:
return .r32Float
case kCVPixelFormatType_TwoComponent8:
return .rg8Unorm
case kCVPixelFormatType_TwoComponent16Half:
return .rg16Float
case kCVPixelFormatType_TwoComponent32Float:
return .rg32Float
case kCVPixelFormatType_32BGRA:
return .bgra8Unorm
case kCVPixelFormatType_32RGBA:
return .rgba8Unorm
case kCVPixelFormatType_64RGBAHalf:
return .rgba16Float
case kCVPixelFormatType_128RGBAFloat:
return .rgba32Float
case kCVPixelFormatType_ARGB2101010LEPacked:
return .bgr10a2Unorm
default:
return nil
}
}
}
33 changes: 33 additions & 0 deletions libobs-metal/MTLCullMode+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/******************************************************************************
Copyright (C) 2024 by Patrick Heyer <PatTheMav@users.noreply.github.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

import Foundation
import Metal

extension MTLCullMode {
/// Conversion of the cull mode into its corresponding `libobs` type
var obsMode: gs_cull_mode {
switch self {
case .back:
return GS_BACK
case .front:
return GS_FRONT
default:
return GS_NEITHER
}
}
}
25 changes: 25 additions & 0 deletions libobs-metal/MTLOrigin+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/******************************************************************************
Copyright (C) 2024 by Patrick Heyer <PatTheMav@users.noreply.github.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

import Foundation
import Metal

extension MTLOrigin: @retroactive Equatable {
public static func == (lhs: MTLOrigin, rhs: MTLOrigin) -> Bool {
lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z
}
}
Loading
Loading