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 @@ ...@@ -14,6 +14,7 @@
#include "d3d/GrD3DBackendContext.h" #include "d3d/GrD3DBackendContext.h"
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_4.h> #include <dxgi1_4.h>
#include <dxgi1_6.h>
#define GR_D3D_CALL_ERRCHECK(X) \ #define GR_D3D_CALL_ERRCHECK(X) \
do \ do \
...@@ -208,6 +209,10 @@ extern "C" ...@@ -208,6 +209,10 @@ extern "C"
{ {
DXGI_ADAPTER_DESC1 desc; DXGI_ADAPTER_DESC1 desc;
hardwareAdapter->GetDesc1(&desc); hardwareAdapter->GetDesc1(&desc);
if ((desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0)
{
return true;
}
std::wstring currentAdapterName(desc.Description); std::wstring currentAdapterName(desc.Description);
for (std::wstring name : adapterBlacklist) for (std::wstring name : adapterBlacklist)
{ {
...@@ -220,32 +225,63 @@ extern "C" ...@@ -220,32 +225,63 @@ extern "C"
return false; return false;
} }
bool defineHardwareAdapter(IDXGIFactory4 *pFactory, IDXGIAdapter1 **ppAdapter) bool defineHardwareAdapter(DXGI_GPU_PREFERENCE adapterPriority, IDXGIFactory4 *pFactory, IDXGIAdapter1 **ppAdapter)
{ {
*ppAdapter = nullptr; *ppAdapter = nullptr;
for (UINT adapterIndex = 0;; ++adapterIndex)
#if defined(__dxgi1_6_h__) && defined(NTDDI_WIN10_RS4)
gr_cp<IDXGIFactory6> factory6;
if (SUCCEEDED(pFactory->QueryInterface(IID_PPV_ARGS(&factory6))))
{ {
IDXGIAdapter1 *pAdapter = nullptr; for (UINT adapterIndex = 0;; ++adapterIndex)
if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapters1(adapterIndex, &pAdapter))
{ {
break; 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();
} }
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) }
#endif
if (*ppAdapter == nullptr)
{
for (UINT adapterIndex = 0;; ++adapterIndex)
{ {
if (isBlacklisted(pAdapter)) IDXGIAdapter1 *pAdapter = nullptr;
if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapters1(adapterIndex, &pAdapter))
{ {
continue; break;
} }
*ppAdapter = pAdapter; if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
return true; {
if (isBlacklisted(pAdapter))
{
pAdapter->Release();
continue;
}
*ppAdapter = pAdapter;
return true;
}
pAdapter->Release();
} }
pAdapter->Release();
} }
return false; return false;
} }
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_createDirectXDevice( 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; gr_cp<IDXGIFactory4> deviceFactory;
if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&deviceFactory)))) if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&deviceFactory))))
...@@ -253,7 +289,7 @@ extern "C" ...@@ -253,7 +289,7 @@ extern "C"
return 0; return 0;
} }
gr_cp<IDXGIAdapter1> hardwareAdapter; gr_cp<IDXGIAdapter1> hardwareAdapter;
if (!defineHardwareAdapter(deviceFactory.get(), &hardwareAdapter)) if (!defineHardwareAdapter((DXGI_GPU_PREFERENCE) adapterPriority, deviceFactory.get(), &hardwareAdapter))
{ {
return 0; return 0;
} }
......
...@@ -2,4 +2,12 @@ package org.jetbrains.skiko ...@@ -2,4 +2,12 @@ package org.jetbrains.skiko
enum class GraphicsApi { enum class GraphicsApi {
UNKNOWN, SOFTWARE, OPENGL, DIRECT3D, VULKAN, METAL 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 ...@@ -6,6 +6,7 @@ import kotlinx.coroutines.withContext
import org.jetbrains.skija.Surface import org.jetbrains.skija.Surface
import org.jetbrains.skija.DirectContext import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.GpuPriority
import org.jetbrains.skiko.SkiaLayer import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties import org.jetbrains.skiko.SkiaLayerProperties
...@@ -64,13 +65,23 @@ internal class Direct3DRedrawer( ...@@ -64,13 +65,23 @@ internal class Direct3DRedrawer(
makeDirectXSurface(device, context, width, height, index) 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) { fun finishFrame(device: Long, context: Long, surface: Long) {
finishFrame(device, context, surface, properties.isVsyncEnabled) 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 makeDirectXContext(device: Long): Long
external fun makeDirectXSurface(device: Long, context: Long, width: Int, height: Int, index: Int): Long external fun makeDirectXSurface(device: Long, context: Long, width: Int, height: Int, index: Int): Long
external fun resizeBuffers(device: Long, width: Int, height: Int) external fun resizeBuffers(device: Long, width: Int, height: Int)
......
...@@ -5,6 +5,7 @@ import kotlinx.coroutines.swing.Swing ...@@ -5,6 +5,7 @@ import kotlinx.coroutines.swing.Swing
import org.jetbrains.skija.BackendRenderTarget import org.jetbrains.skija.BackendRenderTarget
import org.jetbrains.skija.DirectContext import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.GpuPriority
import org.jetbrains.skiko.SkiaLayer import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties import org.jetbrains.skiko.SkiaLayerProperties
import org.jetbrains.skiko.useDrawingSurfacePlatformInfo import org.jetbrains.skiko.useDrawingSurfacePlatformInfo
...@@ -17,7 +18,9 @@ internal class MetalRedrawer( ...@@ -17,7 +18,9 @@ internal class MetalRedrawer(
) : Redrawer { ) : Redrawer {
private var isDisposed = false private var isDisposed = false
private var disposeLock = Any() 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 windowHandle = layer.windowHandle
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) { private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
...@@ -98,10 +101,20 @@ internal class MetalRedrawer( ...@@ -98,10 +101,20 @@ internal class MetalRedrawer(
fun finishFrame() = finishFrame(device) 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 getAdapterName(): String = getAdapterName(device)
fun getAdapterMemorySize(): Long = getAdapterMemorySize(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 makeMetalContext(device: Long): Long
private external fun makeMetalRenderTarget(device: Long, width: Int, height: Int): Long private external fun makeMetalRenderTarget(device: Long, width: Int, height: Int): Long
private external fun disposeDevice(device: Long) private external fun disposeDevice(device: Long)
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#define kOpen 0 #define kOpen 0
#define kGetMuxState 3 #define kGetMuxState 3
#define kDriverClassName "AppleGraphicsControl" #define kDriverClassName "AppleGraphicsControl"
#define AdpapterPriorityAuto 0
#define AdpapterPriorityIntegrated 1
#define AdpapterPriorityDiscrete 2
@interface AWTMetalLayer : CAMetalLayer @interface AWTMetalLayer : CAMetalLayer
...@@ -136,8 +139,15 @@ BOOL isUsingIntegratedGPU() { ...@@ -136,8 +139,15 @@ BOOL isUsingIntegratedGPU() {
return output != 0; return output != 0;
} }
id<MTLDevice> MTLCreateIntegratedDevice() { id<MTLDevice> MTLCreateIntegratedDevice(int adpapterPriority) {
BOOL isIntegratedGPU = isUsingIntegratedGPU(); BOOL isIntegratedGPU = NO;
if (adpapterPriority == AdpapterPriorityAuto) {
isIntegratedGPU = isUsingIntegratedGPU();
} else if (adpapterPriority == AdpapterPriorityIntegrated) {
isIntegratedGPU = YES;
}
id<MTLDevice> gpu = nil; id<MTLDevice> gpu = nil;
if (isIntegratedGPU) { if (isIntegratedGPU) {
...@@ -156,7 +166,7 @@ id<MTLDevice> MTLCreateIntegratedDevice() { ...@@ -156,7 +166,7 @@ id<MTLDevice> MTLCreateIntegratedDevice() {
} }
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMetalDevice( 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]; MetalDevice *device = [MetalDevice new];
...@@ -171,7 +181,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMe ...@@ -171,7 +181,7 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_MetalRedrawer_createMe
[container addSublayer: layer]; [container addSublayer: layer];
layer.javaRef = env->NewGlobalRef(redrawer); layer.javaRef = env->NewGlobalRef(redrawer);
id<MTLDevice> fDevice = MTLCreateIntegratedDevice(); id<MTLDevice> fDevice = MTLCreateIntegratedDevice(adapterPriority);
id<MTLCommandQueue> fQueue = [fDevice newCommandQueue]; id<MTLCommandQueue> fQueue = [fDevice newCommandQueue];
device.container = container; 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