Skip to content

Commit f57b131

Browse files
MikhailGorobetsTheMostDiligent
authored andcommitted
OpenGL: Added option to control desired adapter type in OpenGL (close #450)
1 parent 1fbce38 commit f57b131

4 files changed

Lines changed: 108 additions & 2 deletions

File tree

Graphics/GraphicsEngine/interface/GraphicsTypes.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2023 Diligent Graphics LLC
2+
* Copyright 2019-2024 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -3485,6 +3485,25 @@ struct EngineGLCreateInfo DILIGENT_DERIVE(EngineCreateInfo)
34853485
/// Use IRenderDevice::GetDeviceInfo().NDC to get current NDC.
34863486
Bool ZeroToOneNDZ DEFAULT_INITIALIZER(false);
34873487

3488+
/// The GPU preference allows you to request either the integrated or dedicated GPU
3489+
/// on systems having both onboard and dedicated GPUs. Currently this works only on Windows and Linux.
3490+
///
3491+
/// * On Windows this is done by setting the `NvOptimusEnablement` and `AmdPowerXpressRequestHighPerformance`.
3492+
/// When the Nvidia and AMD drivers see their respective symbol exported and set to nonzero in a program,
3493+
/// they will take precedence over the integrated GPU when creating the OpenGL context.
3494+
///
3495+
/// Unfortunately, there is no way to transfer exported symbols from static libraries
3496+
/// to the executable file without explicitly creating a Module-Definition File (.def).
3497+
///
3498+
/// Therefore you need to explicitly define these variables in your executable file:
3499+
/// https://gist.github.com/statico/6809850727c708f08458
3500+
/// or you can use the `Diligent-GLAdapterSelector` object library as source input to your executable target:
3501+
/// `target_sources(MyExecutable PRIVATE $<TARGET_OBJECTS:Diligent-GLAdapterSelector>)`,
3502+
/// see https://cmake.org/cmake/help/v3.16/manual/cmake-buildsystem.7.html#object-libraries.
3503+
///
3504+
/// * On Linux this affects the `DRI_PRIME` environment variable that is used by Mesa drivers that support PRIME.
3505+
ADAPTER_TYPE PreferredAdapterType DEFAULT_INITIALIZER(ADAPTER_TYPE_UNKNOWN);
3506+
34883507
#if PLATFORM_EMSCRIPTEN
34893508
/// WebGL context attributes.
34903509
WebGLContextAttribs WebGLAttribs;

Graphics/GraphicsEngineOpenGL/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,12 @@ else()
281281
)
282282
endif()
283283

284+
add_library(Diligent-GLAdapterSelector OBJECT "src/GLAdapterSelector.cpp")
285+
target_link_libraries(Diligent-GLAdapterSelector PRIVATE Diligent-BuildSettings)
286+
284287
set_common_target_properties(Diligent-GraphicsEngineOpenGL-shared)
285288
set_common_target_properties(Diligent-GraphicsEngineOpenGL-static)
289+
set_common_target_properties(Diligent-GLAdapterSelector)
286290

287291
source_group("src" FILES ${SOURCE})
288292
if(PLATFORM_WIN32)
@@ -298,6 +302,9 @@ set_target_properties(Diligent-GraphicsEngineOpenGL-static PROPERTIES
298302
set_target_properties(Diligent-GraphicsEngineOpenGL-shared PROPERTIES
299303
FOLDER DiligentCore/Graphics
300304
)
305+
set_target_properties(Diligent-GLAdapterSelector PROPERTIES
306+
FOLDER DiligentCore/Graphics
307+
)
301308

302309
set_source_files_properties(
303310
readme.md PROPERTIES HEADER_FILE_ONLY TRUE
@@ -306,4 +313,5 @@ set_source_files_properties(
306313
if(DILIGENT_INSTALL_CORE)
307314
install_core_lib(Diligent-GraphicsEngineOpenGL-shared)
308315
install_core_lib(Diligent-GraphicsEngineOpenGL-static)
316+
install_core_lib(Diligent-GLAdapterSelector)
309317
endif()

Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2023 Diligent Graphics LLC
2+
* Copyright 2019-2024 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -137,6 +137,38 @@ static void SetDefaultGraphicsAdapterInfo(GraphicsAdapterInfo& AdapterInfo)
137137
AdapterInfo.Queues[0].TextureCopyGranularity[2] = 1;
138138
}
139139

140+
static void SetPreferredAdapter(const EngineGLCreateInfo& EngineCI)
141+
{
142+
bool EnableDedicatedGPU = EngineCI.PreferredAdapterType == ADAPTER_TYPE_DISCRETE;
143+
#if PLATFORM_WIN32
144+
const HMODULE ModuleHandle = GetModuleHandle(nullptr);
145+
Uint64* const NvOptimusEnablement = reinterpret_cast<Uint64*>(GetProcAddress(ModuleHandle, "NvOptimusEnablement"));
146+
Uint64* const AmdPowerXpressRequestHighPerformance = reinterpret_cast<Uint64*>(GetProcAddress(ModuleHandle, "AmdPowerXpressRequestHighPerformance"));
147+
if (!NvOptimusEnablement && !AmdPowerXpressRequestHighPerformance)
148+
{
149+
LOG_WARNING_MESSAGE("Neither NvOptimusEnablement nor AmdPowerXpressRequestHighPerformance symbols found. "
150+
"You need to explicitly define these variables in your executable file: "
151+
"https://gist.github.com/statico/6809850727c708f08458XpressRequestHighPerformance, "
152+
"or you can use the `Diligent-GLAdapterSelector` object library as source input to your executable target: "
153+
"`target_sources(MyExecutable PRIVATE $<TARGET_OBJECTS:Diligent-GLAdapterSelector>)`, "
154+
"see https://cmake.org/cmake/help/v3.16/manual/cmake-buildsystem.7.html#object-libraries).");
155+
}
156+
if (AmdPowerXpressRequestHighPerformance)
157+
{
158+
*AmdPowerXpressRequestHighPerformance = EnableDedicatedGPU;
159+
}
160+
if (NvOptimusEnablement)
161+
{
162+
*NvOptimusEnablement = EnableDedicatedGPU;
163+
}
164+
#elif PLAtTFORM_LINUX
165+
setenv("DRI_PRIME", EnableDedicatedGPU ? "1" : "0", 1);
166+
#else
167+
if (EnableDedicatedGPU)
168+
LOG_WARNING_MESSAGE("Setting preferred adapter type isn't supported on this platform");
169+
#endif
170+
}
171+
140172
void EngineFactoryOpenGLImpl::EnumerateAdapters(Version MinVersion,
141173
Uint32& NumAdapters,
142174
GraphicsAdapterInfo* Adapters) const
@@ -205,6 +237,7 @@ void EngineFactoryOpenGLImpl::CreateDeviceAndSwapChainGL(const EngineGLCreateInf
205237
SetRawAllocator(EngineCI.pRawMemAllocator);
206238
auto& RawMemAllocator = GetRawAllocator();
207239

240+
SetPreferredAdapter(EngineCI);
208241
RenderDeviceGLImpl* pRenderDeviceOpenGL{
209242
NEW_RC_OBJ(RawMemAllocator, "TRenderDeviceGLImpl instance", TRenderDeviceGLImpl)(
210243
RawMemAllocator, this, EngineCI, &SCDesc //
@@ -303,6 +336,7 @@ void EngineFactoryOpenGLImpl::AttachToActiveGLContext(const EngineGLCreateInfo&
303336
SetRawAllocator(EngineCI.pRawMemAllocator);
304337
auto& RawMemAllocator = GetRawAllocator();
305338

339+
SetPreferredAdapter(EngineCI);
306340
RenderDeviceGLImpl* pRenderDeviceOpenGL{
307341
NEW_RC_OBJ(RawMemAllocator, "TRenderDeviceGLImpl instance", TRenderDeviceGLImpl)(
308342
RawMemAllocator, this, EngineCI //
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2024 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#include <cinttypes>
28+
29+
#if PLATFORM_WIN32
30+
# define DILIGENT_INTERFACE_EXPORT __declspec(dllexport)
31+
#elif PLATFORM_LINUX
32+
# define DILIGENT_INTERFACE_EXPORT __attribute__((visibility("default")))
33+
#else
34+
# define DILIGENT_INTERFACE_EXPORT
35+
#endif
36+
37+
/// Let the NVIDIA and AMD know we want to use their graphics card on a dual graphics card system.
38+
extern "C"
39+
{
40+
/// https://community.amd.com/thread/169965
41+
DILIGENT_INTERFACE_EXPORT uint64_t AmdPowerXpressRequestHighPerformance = 0x0;
42+
43+
/// http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
44+
DILIGENT_INTERFACE_EXPORT uint64_t NvOptimusEnablement = 0x0;
45+
}

0 commit comments

Comments
 (0)