Unverified Commit f7938db5 authored by Roman Sedaikin's avatar Roman Sedaikin Committed by GitHub

Adapter priority (#106)

More flexible adapter selection in Metal and DirectX rendering via properties (skiko.metal.gpu.priority, skiko.derectx.gpu.priority).
parent e1c16426
......@@ -14,6 +14,7 @@
#include "d3d/GrD3DBackendContext.h"
#include <d3d12.h>
#include <dxgi1_4.h>
#include <dxgi1_6.h>
#define GR_D3D_CALL_ERRCHECK(X) \
do \
......@@ -208,6 +209,10 @@ extern "C"
{
DXGI_ADAPTER_DESC1 desc;
hardwareAdapter->GetDesc1(&desc);
if ((desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0)
{
return true;
}
std::wstring currentAdapterName(desc.Description);
for (std::wstring name : adapterBlacklist)
{
......@@ -220,9 +225,38 @@ extern "C"
return false;
}
bool defineHardwareAdapter(IDXGIFactory4 *pFactory, IDXGIAdapter1 **ppAdapter)
bool defineHardwareAdapter(DXGI_GPU_PREFERENCE adapterPriority, IDXGIFactory4 *pFactory, IDXGIAdapter1 **ppAdapter)
{
*ppAdapter = nullptr;
#if defined(__dxgi1_6_h__) && defined(NTDDI_WIN10_RS4)
gr_cp<IDXGIFactory6> factory6;
if (SUCCEEDED(pFactory->QueryInterface(IID_PPV_ARGS(&factory6))))
{
for (UINT adapterIndex = 0;; ++adapterIndex)
{
IDXGIAdapter1 *pAdapter = nullptr;
if (!SUCCEEDED(factory6->EnumAdapterByGpuPreference(adapterIndex, adapterPriority, IID_PPV_ARGS(&pAdapter))))
{
break;
}
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
{
if (isBlacklisted(pAdapter))
{
pAdapter->Release();
continue;
}
*ppAdapter = pAdapter;
return true;
}
pAdapter->Release();
}
}
#endif
if (*ppAdapter == nullptr)
{
for (UINT adapterIndex = 0;; ++adapterIndex)
{
IDXGIAdapter1 *pAdapter = nullptr;
......@@ -234,6 +268,7 @@ extern "C"
{
if (isBlacklisted(pAdapter))
{
pAdapter->Release();
continue;
}
*ppAdapter = pAdapter;
......@@ -241,11 +276,12 @@ extern "C"
}
pAdapter->Release();
}
}
return false;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_createDirectXDevice(
JNIEnv *env, jobject redrawer, jlong windowHandle)
JNIEnv *env, jobject redrawer, jint adapterPriority, jlong windowHandle)
{
gr_cp<IDXGIFactory4> deviceFactory;
if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&deviceFactory))))
......@@ -253,7 +289,7 @@ extern "C"
return 0;
}
gr_cp<IDXGIAdapter1> hardwareAdapter;
if (!defineHardwareAdapter(deviceFactory.get(), &hardwareAdapter))
if (!defineHardwareAdapter((DXGI_GPU_PREFERENCE) adapterPriority, deviceFactory.get(), &hardwareAdapter))
{
return 0;
}
......
......@@ -3,3 +3,11 @@ package org.jetbrains.skiko
enum class GraphicsApi {
UNKNOWN, SOFTWARE, OPENGL, DIRECT3D, VULKAN, METAL
}
enum class GpuPriority(val value: String) {
Auto("auto"), Integrated("integrated"), Discrete("discrete");
companion object {
fun parse(value: String?): GpuPriority? = GpuPriority.values().find { it.value == value }
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ import kotlinx.coroutines.withContext
import org.jetbrains.skija.Surface
import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.GpuPriority
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties
......@@ -64,13 +65,23 @@ internal class Direct3DRedrawer(
makeDirectXSurface(device, context, width, height, index)
)
fun createDevice(): Long = createDirectXDevice(layer.windowHandle)
fun createDevice(): Long = createDirectXDevice(getAdapterPriority(), layer.windowHandle)
fun finishFrame(device: Long, context: Long, surface: Long) {
finishFrame(device, context, surface, properties.isVsyncEnabled)
}
external fun createDirectXDevice(windowHandle: Long): Long
fun getAdapterPriority(): Int {
val adapterPriority = GpuPriority.parse(System.getProperty("skiko.directx.gpu.priority"))
return when (adapterPriority) {
GpuPriority.Auto -> 0
GpuPriority.Integrated -> 1
GpuPriority.Discrete -> 2
else -> 0
}
}
external fun createDirectXDevice(adapterPriority: Int, windowHandle: Long): Long
external fun makeDirectXContext(device: Long): Long
external fun makeDirectXSurface(device: Long, context: Long, width: Int, height: Int, index: Int): Long
external fun resizeBuffers(device: Long, width: Int, height: Int)
......
......@@ -5,6 +5,7 @@ import kotlinx.coroutines.swing.Swing
import org.jetbrains.skija.BackendRenderTarget
import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.GpuPriority
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties
import org.jetbrains.skiko.useDrawingSurfacePlatformInfo
......@@ -17,7 +18,9 @@ internal class MetalRedrawer(
) : Redrawer {
private var isDisposed = false
private var disposeLock = Any()
private val device = layer.backedLayer.useDrawingSurfacePlatformInfo(::createMetalDevice)
private val device = layer.backedLayer.useDrawingSurfacePlatformInfo {
createMetalDevice(getAdapterPriority(), it)
}
private val windowHandle = layer.windowHandle
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
......@@ -98,10 +101,20 @@ internal class MetalRedrawer(
fun finishFrame() = finishFrame(device)
fun getAdapterPriority(): Int {
val adapterPriority = GpuPriority.parse(System.getProperty("skiko.metal.gpu.priority"))
return when (adapterPriority) {
GpuPriority.Auto -> 0
GpuPriority.Integrated -> 1
GpuPriority.Discrete -> 2
else -> 0
}
}
fun getAdapterName(): String = getAdapterName(device)
fun getAdapterMemorySize(): Long = getAdapterMemorySize(device)
private external fun createMetalDevice(platformInfo: Long): Long
private external fun createMetalDevice(adapterPriority: Int, platformInfo: Long): Long
private external fun makeMetalContext(device: Long): Long
private external fun makeMetalRenderTarget(device: Long, width: Int, height: Int): Long
private external fun disposeDevice(device: Long)
......
......@@ -17,6 +17,9 @@
#define kOpen 0
#define kGetMuxState 3
#define kDriverClassName "AppleGraphicsControl"
#define AdpapterPriorityAuto 0
#define AdpapterPriorityIntegrated 1
#define AdpapterPriorityDiscrete 2
@interface AWTMetalLayer : CAMetalLayer
......@@ -136,8 +139,15 @@ BOOL isUsingIntegratedGPU() {
return output != 0;
}
id<MTLDevice> MTLCreateIntegratedDevice() {
BOOL isIntegratedGPU = isUsingIntegratedGPU();
id<MTLDevice> MTLCreateIntegratedDevice(int adpapterPriority) {
BOOL isIntegratedGPU = NO;
if (adpapterPriority == AdpapterPriorityAuto) {
isIntegratedGPU = isUsingIntegratedGPU();
} else if (adpapterPriority == AdpapterPriorityIntegrated) {
isIntegratedGPU = YES;
}
id<MTLDevice> gpu = nil;
if (isIntegratedGPU) {
......@@ -156,7 +166,7 @@ id<MTLDevice> MTLCreateIntegratedDevice() {
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMetalDevice(
JNIEnv *env, jobject redrawer, jlong platformInfoPtr)
JNIEnv *env, jobject redrawer, jint adapterPriority, jlong platformInfoPtr)
{
MetalDevice *device = [MetalDevice new];
......@@ -171,7 +181,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMe
[container addSublayer: layer];
layer.javaRef = env->NewGlobalRef(redrawer);
id<MTLDevice> fDevice = MTLCreateIntegratedDevice();
id<MTLDevice> fDevice = MTLCreateIntegratedDevice(adapterPriority);
id<MTLCommandQueue> fQueue = [fDevice newCommandQueue];
device.container = container;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment