Skip to content
Open
19 changes: 11 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,8 @@ macro(AddApplicationInternal Target Executable)
add_dependencies(${Target} runtime_deps)
endif()

set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS ${A_Flags})
set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS ${A_CompileFlags})
set_property(TARGET ${Target} APPEND PROPERTY LINK_OPTIONS ${A_LinkFlags})
set_property(TARGET ${Target} APPEND PROPERTY INCLUDE_DIRECTORIES ${ENGINE_DIR} ${MOUNT_DIR} ${LIB_DIR})
set_property(TARGET ${Target} APPEND PROPERTY COMPILE_DEFINITIONS ${A_Definitions})
set_target_properties(${Target} PROPERTIES OUTPUT_NAME "${Executable}" PREFIX "" FOLDER "engine")
Expand All @@ -846,13 +847,14 @@ endmacro()

function(AddApplication)
set(oneValueArgs Target ExecutableName)
set(multiValueArgs ApplicationMain Definitions Flags CompileFeatures Files Libs Tests)
set(multiValueArgs ApplicationMain Definitions CompileFlags LinkFlags Files Libs Tests)
cmake_parse_arguments(A "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

# Reuse object files between the real application and the test one
add_library(${A_Target}-objects OBJECT EXCLUDE_FROM_ALL ${A_Files} ${PCH_FILE})
target_link_libraries(${A_Target}-objects engine-lib ${A_Libs} ${LIBS_BASE} ${CPP23SupportLibrary})
set_property(TARGET ${A_Target}-objects APPEND PROPERTY COMPILE_OPTIONS ${A_Flags})
set_property(TARGET ${A_Target}-objects APPEND PROPERTY COMPILE_OPTIONS ${A_CompileFlags})
set_property(TARGET ${A_Target}-objects APPEND PROPERTY LINK_OPTIONS ${A_LinkFlags})
set_property(TARGET ${A_Target}-objects APPEND PROPERTY INCLUDE_DIRECTORIES ${ENGINE_DIR} ${MOUNT_DIR} ${LIB_DIR})
set_property(TARGET ${A_Target}-objects APPEND PROPERTY COMPILE_DEFINITIONS ${A_Definitions})

Expand Down Expand Up @@ -893,8 +895,8 @@ if (NOT NACL)
ExecutableName dummyapp
Definitions USELESS_DEFINITION_TO_AVOID_PCH_ISSUE
ApplicationMain ${ENGINE_DIR}/null/NullApplication.cpp
Flags ${WARNINGS}
Files ${COMMON_DIR}/Util.h # must be nonempty
CompileFlags ${WARNINGS}
Files ${DUMMYAPPLIST}
Tests ${ENGINETESTLIST}
)
endif()
Expand All @@ -920,7 +922,8 @@ if (BUILD_CLIENT)
ExecutableName ${CLIENT_EXECUTABLE_NAME}
ApplicationMain ${ENGINE_DIR}/client/ClientApplication.cpp
Definitions ${Definitions}
Flags ${WARNINGS}
CompileFlags ${WARNINGS};${OPENMP_COMPILE_FLAG}
LinkFlags ${OPENMP_LINK_FLAG}
Files ${WIN_RC} ${BUILDINFOLIST} ${QCOMMONLIST} ${SERVERLIST} ${CLIENTBASELIST} ${CLIENTLIST}
Libs ${LIBS_CLIENT} ${LIBS_CLIENTBASE} ${LIBS_ENGINE}
Tests ${CLIENTTESTLIST}
Expand All @@ -938,7 +941,7 @@ if (BUILD_SERVER)
ExecutableName daemonded
ApplicationMain ${ENGINE_DIR}/server/ServerApplication.cpp
Definitions BUILD_ENGINE BUILD_SERVER
Flags ${WARNINGS}
CompileFlags ${WARNINGS}
Files ${WIN_RC} ${BUILDINFOLIST} ${QCOMMONLIST} ${SERVERLIST} ${DEDSERVERLIST}
Libs ${LIBS_ENGINE}
Tests ${ENGINETESTLIST}
Expand All @@ -951,7 +954,7 @@ if (BUILD_TTY_CLIENT)
ExecutableName daemon-tty
ApplicationMain ${ENGINE_DIR}/client/ClientApplication.cpp
Definitions BUILD_ENGINE BUILD_TTY_CLIENT
Flags ${WARNINGS}
CompileFlags ${WARNINGS}
Files ${WIN_RC} ${BUILDINFOLIST} ${QCOMMONLIST} ${SERVERLIST} ${CLIENTBASELIST} ${TTYCLIENTLIST}
Libs ${LIBS_CLIENTBASE} ${LIBS_ENGINE}
Tests ${ENGINETESTLIST}
Expand Down
20 changes: 20 additions & 0 deletions cmake/DaemonFlags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ if (USE_FLOAT_EXCEPTIONS)
add_definitions(-DDAEMON_USE_FLOAT_EXCEPTIONS)
endif()

if (NOT NACL AND BUILD_CLIENT)
option(USE_OPENMP "Use OpenMP to parallelize some tasks" OFF)
endif()

if (MSVC)
set_c_cxx_flag("/MP")

Expand All @@ -267,6 +271,11 @@ if (MSVC)
set_cxx_flag("/std:c++23preview")
endif()

if (NOT NACL AND BUILD_CLIENT AND USE_OPENMP)
# Flag checks doen't work with MSVC so we assume it's there.
set(OPENMP_COMPILE_FLAG "/openmp")
endif()

if (USE_FAST_MATH)
set_c_cxx_flag("/fp:fast")
else()
Expand Down Expand Up @@ -362,6 +371,17 @@ else()
endif()
endif()

if (NOT NACL AND BUILD_CLIENT AND USE_OPENMP)
check_CXX_compiler_flag("-fopenmp" FLAG_FOPENMP)

if (FLAG_FOPENMP)
set(OPENMP_COMPILE_FLAG "-fopenmp")
set(OPENMP_LINK_FLAG "-fopenmp")
else()
message(WARNING "Missing OpenMP")
endif()
endif()

if (NACL AND USE_NACL_SAIGO AND SAIGO_ARCH STREQUAL "arm")
# Saigo produces broken arm builds when optimizing them.
# See: https://github.com/Unvanquished/Unvanquished/issues/3297
Expand Down
15 changes: 15 additions & 0 deletions src.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ set(ENGINELIST
${ENGINE_DIR}/framework/CvarSystem.h
${ENGINE_DIR}/framework/LogSystem.cpp
${ENGINE_DIR}/framework/LogSystem.h
${ENGINE_DIR}/framework/OmpSystem.cpp
${ENGINE_DIR}/framework/OmpSystem.h
${ENGINE_DIR}/framework/Resource.cpp
${ENGINE_DIR}/framework/Resource.h
${ENGINE_DIR}/framework/System.cpp
Expand All @@ -207,6 +209,11 @@ set(ENGINELIST
${ENGINE_DIR}/RefAPI.h
)

set(OMPLIST
${ENGINE_DIR}/framework/OmpSystem.cpp
${ENGINE_DIR}/framework/OmpSystem.h
)

if (WIN32)
set(ENGINELIST ${ENGINELIST}
${ENGINE_DIR}/sys/con_passive.cpp
Expand Down Expand Up @@ -271,6 +278,7 @@ set(CLIENTBASELIST
)

set(CLIENTLIST
${OMPLIST}
${ENGINE_DIR}/audio/ALObjects.cpp
${ENGINE_DIR}/audio/ALObjects.h
${ENGINE_DIR}/audio/Audio.cpp
Expand Down Expand Up @@ -304,16 +312,23 @@ set(CLIENTTESTLIST ${ENGINETESTLIST}
)

set(TTYCLIENTLIST
${OMPLIST}
${ENGINE_DIR}/null/NullAudio.cpp
${ENGINE_DIR}/null/NullKeyboard.cpp
${ENGINE_DIR}/null/null_input.cpp
${ENGINE_DIR}/null/null_renderer.cpp
)

set(DEDSERVERLIST
${OMPLIST}
${ENGINE_DIR}/null/NullKeyboard.cpp
${ENGINE_DIR}/null/null_client.cpp
${ENGINE_DIR}/null/null_input.cpp
)

set(DUMMYAPPLIST
${OMPLIST}
${COMMON_DIR}/Util.h
)

set(WIN_RC ${ENGINE_DIR}/sys/windows-resource/icon.rc)
100 changes: 100 additions & 0 deletions src/engine/framework/OmpSystem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2025, Daemon Developers
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Daemon developers nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include <algorithm>

#include "CvarSystem.h"
#include "OmpSystem.h"

#if defined(_OPENMP)
#include "omp.h"
#endif

#if defined(_OPENMP)
static Cvar::Range<Cvar::Cvar<int>> common_ompThreads(
"common.ompThreads", "OpenMP threads", Cvar::NONE, 0, 0, 32 );
#endif

namespace Omp {
#if defined(_OPENMP)
static int ompMaxThreads = 1;
#endif

static int ompThreads = 1;

static void ReadMaxThreads()
{
#if defined(_OPENMP)
ompMaxThreads = omp_get_max_threads();
#endif
}

void EnlistThreads()
{
#if defined(_OPENMP)
omp_set_num_threads( ompThreads );
#endif
}

void SetupThreads()
{
#if defined(_OPENMP)
if ( common_ompThreads.Get() )
{
ompThreads = common_ompThreads.Get();
}
else if ( ompMaxThreads <= 4 )
{
ompThreads = ompMaxThreads;
}
else if ( ompMaxThreads <= 16 )
{
ompThreads = ompMaxThreads - ( ompMaxThreads / 4 );
}
else
{
ompThreads = 16;
}
#endif

EnlistThreads();
}

void Init()
{
ReadMaxThreads();
SetupThreads();
}

int GetThreads()
{
return ompThreads;
}
}
41 changes: 41 additions & 0 deletions src/engine/framework/OmpSystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2025, Daemon Developers
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Daemon developers nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#ifndef COMMON_OMP_SYSTEM_H_
#define COMMON_OMP_SYSTEM_H_

namespace Omp {
void EnlistThreads();
void SetupThreads();
void Init();
int GetThreads();
};

#endif // COMMON_OMP_SYSTEM_H_
3 changes: 3 additions & 0 deletions src/engine/framework/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ConsoleHistory.h"
#include "CommandSystem.h"
#include "LogSystem.h"
#include "OmpSystem.h"
#include "System.h"
#include "CrashDump.h"
#include "CvarSystem.h"
Expand Down Expand Up @@ -968,6 +969,8 @@ static void Init(int argc, char** argv)
for (auto& cvar: cmdlineArgs.cvars)
Cvar::SetValue(cvar.first, cvar.second);

Omp::Init();
Copy link
Member Author

@illwieckz illwieckz Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slipher Maybe it's a better place there? Given the previous line I assume the Cvar system is already initialized.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems OK


// Load the console history
Console::History::Load();

Expand Down
3 changes: 3 additions & 0 deletions src/engine/qcommon/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Maryland 20850 USA.
#include "framework/CommandSystem.h"
#include "framework/CvarSystem.h"
#include "framework/LogSystem.h"
#include "framework/OmpSystem.h"
#include "framework/System.h"
#include "sys/sys_events.h"
#include <common/FileSystem.h>
Expand Down Expand Up @@ -783,6 +784,8 @@ static Cvar::Cvar<bool> showTraceStats("common.showTraceStats", "are physics tra

void Com_Frame()
{
Omp::SetupThreads();

int msec, minMsec;
static int lastTime = 0;
//int key;
Expand Down
3 changes: 3 additions & 0 deletions src/engine/renderer/tr_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// tr_backend.c

#include "framework/OmpSystem.h"
#include "tr_local.h"
#include "gl_shader.h"
#include "Material.h"
Expand Down Expand Up @@ -3869,6 +3870,8 @@ RB_RenderThread
*/
void RB_RenderThread()
{
Omp::EnlistThreads();

const void *data;

// wait for either a rendering command or a quit command
Expand Down
16 changes: 16 additions & 0 deletions src/engine/renderer/tr_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// tr_init.c -- functions that are not called every frame
#include "tr_local.h"
#include "framework/CvarSystem.h"
#include "framework/OmpSystem.h"
#include "DetectGLVendors.h"
#include "Material.h"
#include "GeometryCache.h"
Expand Down Expand Up @@ -1057,6 +1058,21 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p
Log::Notice("Using dual processor acceleration." );
}

#if defined(_OPENMP)
int ompThreads = Omp::GetThreads();

if ( ompThreads == 1 )
{
Log::Notice("%sNot using OpenMP parallelism: only one thread.", Color::ToString( Color::Red ) );
}
else
{
Log::Notice("%sUsing OpenMP parallelism with %d threads.", Color::ToString( Color::Green ), ompThreads );
}
#else
Log::Notice("%sNot using OpenMP parallelism: unavailable.", Color::ToString( Color::Red ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it makes sense to output this in red, which is presumably even worse than a yellow warning, since the OpenMP would only be used by a minority of players with the worst GPUs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes. I can change that.

#endif

if ( r_finish->integer )
{
Log::Notice("Forcing glFinish." );
Expand Down
Loading
Loading