Partial improvement to selector
This commit is contained in:
@@ -83,13 +83,28 @@ public class GPUSelectorWindows2 {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record AdapterInfo(int type, long luid, int vendor, int device, int subSystem) {
|
private static int queryAdapterIcd(int handle, String[] out) {
|
||||||
|
int ret;
|
||||||
|
try (var stack = MemoryStack.stackPush()) {
|
||||||
|
var buff = stack.calloc(260*2+8).order(ByteOrder.nativeOrder());
|
||||||
|
//KMTQAITYPE_UMOPENGLINFO
|
||||||
|
if ((ret=query(handle, 2, buff))<0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
int len = Math.min(MemoryUtil.memLengthNT2(buff), 260*2);
|
||||||
|
out[0] = MemoryUtil.memUTF16(buff.limit(len));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private record AdapterInfo(String icdPath, int type, long luid, int vendor, int device, int subSystem) {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String LUID = Integer.toHexString((int) ((luid>>>32)&0xFFFFFFFFL))+"-"+Integer.toHexString((int) (luid&0xFFFFFFFFL));
|
String LUID = Integer.toHexString((int) ((luid>>>32)&0xFFFFFFFFL))+"-"+Integer.toHexString((int) (luid&0xFFFFFFFFL));
|
||||||
return "{type=%s, luid=%s, vendor=%s, device=%s, subSys=%s}".formatted(Integer.toString(type),LUID, Integer.toHexString(vendor), Integer.toHexString(device), Integer.toHexString(subSystem));
|
return "{type=%s, luid=%s, vendor=%s, device=%s, subSys=%s, icd=\"%s\"}".formatted(Integer.toString(type),LUID, Integer.toHexString(vendor), Integer.toHexString(device), Integer.toHexString(subSystem), icdPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private record PCIDeviceId(int vendor, int device, int subVendor, int subSystem, int revision, int busType) {}
|
private record PCIDeviceId(int vendor, int device, int subVendor, int subSystem, int revision, int busType) {}
|
||||||
private static int queryPCIAddress(int handle, int index, PCIDeviceId[] deviceOut) {
|
private static int queryPCIAddress(int handle, int index, PCIDeviceId[] deviceOut) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -139,6 +154,16 @@ public class GPUSelectorWindows2 {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String[] icd = new String[1];
|
||||||
|
if ((ret = queryAdapterIcd(handle, icd))<0) {
|
||||||
|
Logger.error("Query icd error: " + ret);
|
||||||
|
//We errored
|
||||||
|
if (closeHandle(handle) < 0) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PCIDeviceId[] out = new PCIDeviceId[1];
|
PCIDeviceId[] out = new PCIDeviceId[1];
|
||||||
//Get the root adapter device
|
//Get the root adapter device
|
||||||
@@ -152,7 +177,7 @@ public class GPUSelectorWindows2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int subSys = (out[0].subSystem<<16)|out[0].subVendor;//It seems the pci subsystem address is a joined integer
|
int subSys = (out[0].subSystem<<16)|out[0].subVendor;//It seems the pci subsystem address is a joined integer
|
||||||
consumer.accept(new AdapterInfo(type[0], luid, out[0].vendor, out[0].device, subSys));
|
consumer.accept(new AdapterInfo(icd[0], type[0], luid, out[0].vendor, out[0].device, subSys));
|
||||||
|
|
||||||
if (closeHandle(handle) < 0) {
|
if (closeHandle(handle) < 0) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
@@ -173,7 +198,7 @@ public class GPUSelectorWindows2 {
|
|||||||
l >>= 8;
|
l >>= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static byte[] createFinishedHDCStub(long luid, long D3DKMTOpenAdapterFromLuid) {
|
private static byte[] createFinishedHDCStub(long luid) {
|
||||||
byte[] stub = new byte[HDC_STUB.length];
|
byte[] stub = new byte[HDC_STUB.length];
|
||||||
for (int i = 0; i < stub.length; i++) {
|
for (int i = 0; i < stub.length; i++) {
|
||||||
stub[i] = (byte) HDC_STUB[i];
|
stub[i] = (byte) HDC_STUB[i];
|
||||||
@@ -187,6 +212,13 @@ public class GPUSelectorWindows2 {
|
|||||||
private static final long D3DKMTOpenAdapterFromHdc = apiGetFunctionAddressOptional(GDI32.getLibrary(), "D3DKMTOpenAdapterFromHdc");
|
private static final long D3DKMTOpenAdapterFromHdc = apiGetFunctionAddressOptional(GDI32.getLibrary(), "D3DKMTOpenAdapterFromHdc");
|
||||||
private static final long VirtualProtect = apiGetFunctionAddressOptional(Kernel32.getLibrary(), "VirtualProtect");
|
private static final long VirtualProtect = apiGetFunctionAddressOptional(Kernel32.getLibrary(), "VirtualProtect");
|
||||||
|
|
||||||
|
private static byte[] toByteArray(int... array) {
|
||||||
|
byte[] res = new byte[array.length];
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
res[i] = (byte) array[i];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
private static void VirtualProtect(long addr, long size) {
|
private static void VirtualProtect(long addr, long size) {
|
||||||
try (var stack = MemoryStack.stackPush()) {
|
try (var stack = MemoryStack.stackPush()) {
|
||||||
var oldProtection = stack.calloc(4);
|
var oldProtection = stack.calloc(4);
|
||||||
@@ -204,38 +236,62 @@ public class GPUSelectorWindows2 {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Logger.info("AdapterLuid callback at: " + Long.toHexString(D3DKMTOpenAdapterFromLuid));
|
Logger.info("AdapterLuid callback at: " + Long.toHexString(D3DKMTOpenAdapterFromLuid));
|
||||||
var stub = createFinishedHDCStub(adapterLuid, D3DKMTOpenAdapterFromLuid);
|
var stub = createFinishedHDCStub(adapterLuid);
|
||||||
|
|
||||||
VirtualProtect(D3DKMTOpenAdapterFromHdc, stub.length);
|
VirtualProtect(D3DKMTOpenAdapterFromHdc, stub.length);
|
||||||
memcpy(D3DKMTOpenAdapterFromHdc, stub);
|
memcpy(D3DKMTOpenAdapterFromHdc, stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void installQueryStub() {
|
private static byte[] createIntelStub(long origA, long origB, long jmpA, long jmpB) {
|
||||||
|
byte[] stub = toByteArray(0xFE, 0x0D, 0x63, 0x00, 0x00, 0x00, 0x80, 0x3D, 0x5C, 0x00, 0x00, 0x00, 0x02, 0x75, 0x07, 0x48, 0x31, 0xC0, 0x48, 0xF7, 0xD0, 0xC3, 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x8B, 0x0D, 0x43, 0x00, 0x00, 0x00, 0x48, 0x89, 0x08, 0x48, 0x8B, 0x0D, 0x41, 0x00, 0x00, 0x00, 0x48, 0x89, 0x48, 0x08, 0x80, 0x3D, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x74, 0x1D, 0x50, 0xFF, 0xD0, 0x58, 0x48, 0x8B, 0x0D, 0x31, 0x00, 0x00, 0x00, 0x48, 0x89, 0x08, 0x48, 0x8B, 0x0D, 0x2F, 0x00, 0x00, 0x00, 0x48, 0x89, 0x48, 0x08, 0x48, 0x31, 0xC0, 0xC3, 0x48, 0x8B, 0x41, 0x08, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x31, 0xC0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
|
||||||
|
insertLong(D3DKMTQueryAdapterInfo, stub, 24);
|
||||||
|
stub[0x69] = 3;
|
||||||
|
insertLong(origA, stub, 0x6a);
|
||||||
|
insertLong(origB, stub, 0x6a+8);
|
||||||
|
insertLong(jmpA, stub, 0x6a+16);
|
||||||
|
insertLong(jmpB, stub, 0x6a+24);
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] createSimpleStub(long origA, long origB) {
|
||||||
|
byte[] stub = toByteArray(0x48, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0, 0x48, 0x8B, 0x0D, 0x15, 0x00, 0x00, 0x00, 0x48, 0x89, 0x08, 0x48, 0x8B, 0x0D, 0x13, 0x00, 0x00, 0x00, 0x48, 0x89, 0x48, 0x08, 0x48, 0x31, 0xC0, 0x48, 0xF7, 0xD0, 0xC3, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0);
|
||||||
|
insertLong(D3DKMTQueryAdapterInfo, stub, 2);
|
||||||
|
insertLong(origA, stub, 38);
|
||||||
|
insertLong(origB, stub, 38+8);
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void installQueryStub(boolean installIntelBypass) {
|
||||||
if (D3DKMTQueryAdapterInfo == 0 || VirtualProtect == 0) {
|
if (D3DKMTQueryAdapterInfo == 0 || VirtualProtect == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualProtect(D3DKMTQueryAdapterInfo, 0x10);
|
VirtualProtect(D3DKMTQueryAdapterInfo, 0x10);
|
||||||
|
int MAX_STUB_SIZE = 1024;
|
||||||
|
long stubPtr = MemoryUtil.nmemAlloc(MAX_STUB_SIZE);
|
||||||
|
VirtualProtect(stubPtr, MAX_STUB_SIZE);
|
||||||
|
Logger.info("Do stub at: " + Long.toHexString(stubPtr));
|
||||||
|
|
||||||
var fixAndRetStub = new byte[] { 0x48, (byte) 0xB8, 0, 0, 0, 0, 0, 0, 0, 0, 0x48, (byte) 0x8B, 0x0D, 0x15, 0x00, 0x00, 0x00, 0x48, (byte) 0x89, 0x08, 0x48, (byte) 0x8B, 0x0D, 0x13, 0x00, 0x00, 0x00, 0x48, (byte) 0x89, 0x48, 0x08, 0x48, 0x31, (byte) 0xC0, 0x48, (byte) 0xF7, (byte) 0xD0, (byte) 0xC3, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0};
|
long origA = MemoryUtil.memGetLong(D3DKMTQueryAdapterInfo);
|
||||||
long stubPtr = MemoryUtil.nmemAlloc(fixAndRetStub.length);
|
long origB = MemoryUtil.memGetLong(D3DKMTQueryAdapterInfo+8);
|
||||||
VirtualProtect(stubPtr, fixAndRetStub.length);
|
|
||||||
|
|
||||||
|
|
||||||
insertLong(D3DKMTQueryAdapterInfo, fixAndRetStub, 2);
|
|
||||||
insertLong((MemoryUtil.memGetLong(D3DKMTQueryAdapterInfo)), fixAndRetStub, 38);
|
|
||||||
insertLong((MemoryUtil.memGetLong(D3DKMTQueryAdapterInfo+8)), fixAndRetStub, 38+8);
|
|
||||||
|
|
||||||
memcpy(stubPtr, fixAndRetStub);
|
|
||||||
Logger.info("Restore stub at: " + Long.toHexString(stubPtr));
|
|
||||||
|
|
||||||
|
|
||||||
var jmpStub = new byte[]{ 0x48, (byte) 0xB8, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xFF, (byte) 0xE0};
|
var jmpStub = new byte[]{ 0x48, (byte) 0xB8, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xFF, (byte) 0xE0};
|
||||||
insertLong(stubPtr, jmpStub, 2);
|
insertLong(stubPtr, jmpStub, 2);
|
||||||
|
|
||||||
memcpy(D3DKMTQueryAdapterInfo, jmpStub);
|
memcpy(D3DKMTQueryAdapterInfo, jmpStub);
|
||||||
Logger.info("D3DKMTQueryAdapterInfo at: " + Long.toHexString(D3DKMTQueryAdapterInfo));
|
Logger.info("D3DKMTQueryAdapterInfo at: " + Long.toHexString(D3DKMTQueryAdapterInfo));
|
||||||
|
|
||||||
|
long jmpA = MemoryUtil.memGetLong(D3DKMTQueryAdapterInfo);
|
||||||
|
long jmpB = MemoryUtil.memGetLong(D3DKMTQueryAdapterInfo+8);
|
||||||
|
|
||||||
|
byte[] stub;
|
||||||
|
if (installIntelBypass) {
|
||||||
|
stub = createIntelStub(origA, origB, jmpA, jmpB);
|
||||||
|
} else {
|
||||||
|
stub = createSimpleStub(origA, origB);
|
||||||
|
}
|
||||||
|
memcpy(stubPtr, stub);
|
||||||
|
Logger.info("QueryAdapterInfo stubs installed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -251,7 +307,7 @@ public class GPUSelectorWindows2 {
|
|||||||
var adapter = adapters.get(index);
|
var adapter = adapters.get(index);
|
||||||
|
|
||||||
installHDCStub(adapter.luid);
|
installHDCStub(adapter.luid);
|
||||||
installQueryStub();
|
installQueryStub(adapter.icdPath.matches("\\\\ig[a-z0-9]+icd(32|64)\\.dll$"));
|
||||||
|
|
||||||
setPCIProperties(1/*USER*/, adapter.vendor, adapter.device, adapter.subSystem);
|
setPCIProperties(1/*USER*/, adapter.vendor, adapter.device, adapter.subSystem);
|
||||||
setPCIProperties(2/*USER GLOBAL*/, adapter.vendor, adapter.device, adapter.subSystem);
|
setPCIProperties(2/*USER GLOBAL*/, adapter.vendor, adapter.device, adapter.subSystem);
|
||||||
|
|||||||
Reference in New Issue
Block a user