You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Added support for compiling Vulkan PSO's in separate process
#rb jeannoe.morissette #preflight 62ff8206086f90bbc4fe751f [CL 21499839 by jeannoe morissette in ue5-main branch]
This commit is contained in:
@@ -214,7 +214,7 @@ import android.widget.TextView.OnEditorActionListener;
|
||||
import android.content.BroadcastReceiver;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import com.epicgames.unreal.oglservices.OGLProgramServiceAccessor;
|
||||
import com.epicgames.unreal.psoservices.PSOProgramServiceAccessor;
|
||||
//$${gameActivityImportAdditions}$$
|
||||
|
||||
//$${gameActivityPostImportAdditions}$$
|
||||
@@ -485,7 +485,7 @@ public class GameActivity extends $${gameActivitySuperClass}$$ implements Surfac
|
||||
public boolean bSupportsFloatingPointRenderTargets = false;
|
||||
private String EGLErrorStatus = "UNSET";
|
||||
|
||||
private OGLProgramServiceAccessor mOGLProgramServiceAccessor = new OGLProgramServiceAccessor();
|
||||
private PSOProgramServiceAccessor mPSOProgramServiceAccessor = new PSOProgramServiceAccessor();
|
||||
|
||||
static final private AtomicBoolean bIsActivityPaused = new AtomicBoolean(true);
|
||||
static public boolean IsActivityPaused() { return bIsActivityPaused.get();}
|
||||
@@ -3194,7 +3194,7 @@ public class GameActivity extends $${gameActivitySuperClass}$$ implements Surfac
|
||||
|
||||
//$${gameActivityOnCreateAdditions}$$
|
||||
//$${gameActivityOnCreateFinalAdditions}$$
|
||||
mOGLProgramServiceAccessor.Init(this);
|
||||
mPSOProgramServiceAccessor.Init(this);
|
||||
|
||||
Log.debug("==============> GameActive.onCreate complete!");
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
|
||||
public class OGLProgramService1 extends OGLProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
|
||||
public class OGLProgramService2 extends OGLProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
|
||||
public class OGLProgramService3 extends OGLProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
|
||||
public class OGLProgramService4 extends OGLProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
|
||||
public class OGLProgramService5 extends OGLProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
|
||||
public class OGLProgramService6 extends OGLProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
|
||||
public class OGLProgramService7 extends OGLProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService1 extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService2 extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService3 extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService4 extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService5 extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService6 extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class OGLProgramService7 extends PSOProgramService
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
@@ -40,7 +40,7 @@ import java.util.logging.LogRecord;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
public class PSOProgramService extends Service implements Logger.ILoggerCallback
|
||||
{
|
||||
private final String TAG = this.getClass().getSimpleName();
|
||||
|
||||
@@ -50,6 +50,7 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
static final String VS_Key = "v";
|
||||
static final String PS_Key = "p";
|
||||
static final String CS_Key = "c";
|
||||
static final String PSOData_Key = "pso";
|
||||
static final String JobContext_Key = "jtx";
|
||||
static final String JobID_Key = "jid";
|
||||
static final String ServiceID_Key = "sid";
|
||||
@@ -203,11 +204,16 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
}
|
||||
}
|
||||
|
||||
public OGLProgramService()
|
||||
public PSOProgramService()
|
||||
{
|
||||
OGLUncaughtExceptionHandler.init();
|
||||
}
|
||||
|
||||
public boolean UseVulkan()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent)
|
||||
@@ -231,18 +237,35 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_LINKPROGRAM:
|
||||
beginTrace("OGLProgramService.handleMessage");
|
||||
String VS = msg.getData().getString(VS_Key);
|
||||
String PS = msg.getData().getString(PS_Key);
|
||||
String CS = msg.getData().getString(CS_Key);
|
||||
int JobID = msg.getData().getInt(JobID_Key);
|
||||
int ServiceID = msg.getData().getInt(ServiceID_Key);
|
||||
beginTrace("PSOProgramService.handleMessage");
|
||||
if(UseVulkan())
|
||||
{
|
||||
byte[] VS = msg.getData().getByteArray(VS_Key);
|
||||
byte[] PS = msg.getData().getByteArray(PS_Key);
|
||||
byte[] PSOData = msg.getData().getByteArray(PSOData_Key);
|
||||
int JobID = msg.getData().getInt(JobID_Key);
|
||||
int ServiceID = msg.getData().getInt(ServiceID_Key);
|
||||
|
||||
byte[] JobContext = msg.getData().getByteArray(JobContext_Key);
|
||||
byte[] JobContext = msg.getData().getByteArray(JobContext_Key);
|
||||
|
||||
//logger.verbose("Processing program job "+JobID);
|
||||
ProcessProgramRequest(msg.replyTo, JobID, ServiceID, JobContext, VS, PS, CS);
|
||||
//logger.verbose("Processing program job "+JobID);
|
||||
ProcessVulkanProgramRequest(msg.replyTo, JobID, ServiceID, JobContext, VS, PS, PSOData);
|
||||
}
|
||||
else
|
||||
{
|
||||
String VS = msg.getData().getString(VS_Key);
|
||||
String PS = msg.getData().getString(PS_Key);
|
||||
String CS = msg.getData().getString(CS_Key);
|
||||
int JobID = msg.getData().getInt(JobID_Key);
|
||||
int ServiceID = msg.getData().getInt(ServiceID_Key);
|
||||
|
||||
byte[] JobContext = msg.getData().getByteArray(JobContext_Key);
|
||||
|
||||
//logger.verbose("Processing program job "+JobID);
|
||||
ProcessGLProgramRequest(msg.replyTo, JobID, ServiceID, JobContext, VS, PS, CS);
|
||||
}
|
||||
endTrace();
|
||||
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
@@ -250,7 +273,31 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessProgramRequest(Messenger replyTo, int JobID, int ServiceID, byte[] JobContext, String VS, String PS, String CS)
|
||||
public void ProcessVulkanProgramRequest(Messenger replyTo, int JobID, int ServiceID, byte[] JobContext, byte[] VS, byte[] PS, byte[] PSOData)
|
||||
{
|
||||
ByteBuffer Result = null;
|
||||
try
|
||||
{
|
||||
byte[] PipelineCache = compileVulkanPSO(JobID, VS, PS, PSOData);
|
||||
Result = ByteBuffer.allocate(PipelineCache.length);
|
||||
Result.order(ByteOrder.nativeOrder());
|
||||
Result.put(PipelineCache);
|
||||
|
||||
//logger.verbose(JobID+" CompileAndLink() "+ (Result == null ? "null res " : Result.toString()));
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
SendFail(replyTo, ServiceID, JobID, JobContext, e.getMessage());
|
||||
}
|
||||
|
||||
if(Result != null)
|
||||
{
|
||||
//logger.verbose(JobID+" SendSuccess() ");
|
||||
SendSuccess(replyTo, ServiceID, JobID, JobContext, Result.array());
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessGLProgramRequest(Messenger replyTo, int JobID, int ServiceID, byte[] JobContext, String VS, String PS, String CS)
|
||||
{
|
||||
ByteBuffer Result = null;
|
||||
try
|
||||
@@ -264,6 +311,7 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
}
|
||||
Result = CompileAndLink(JobID, VS, PS, CS);
|
||||
//logger.verbose(JobID+" CompileAndLink() "+ (Result == null ? "null res " : Result.toString()));
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
SendFail(replyTo, ServiceID, JobID, JobContext, e.getMessage());
|
||||
@@ -290,14 +338,30 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
|
||||
Logger.RegisterCallback(this);
|
||||
logger.verbose("oncreate " );
|
||||
initGLContext();
|
||||
if(!UseVulkan())
|
||||
{
|
||||
logger.verbose("initGLContext " );
|
||||
initGLContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.verbose("initVulkanContext " );
|
||||
initVulkanContext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
logger.verbose("onDestroy" );
|
||||
destroyGLContext();
|
||||
if(!UseVulkan())
|
||||
{
|
||||
destroyGLContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
shutdownVulkanContext();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@@ -314,8 +378,8 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
}
|
||||
throw new RuntimeException("1000!");
|
||||
}
|
||||
beginTrace("OGLProgramService.SendSuccess");
|
||||
Message msg = Message.obtain(null, OGLProgramService.MSG_LINKPROGRAM_RESPONSE, 0, 0);
|
||||
beginTrace("PSOProgramService.SendSuccess");
|
||||
Message msg = Message.obtain(null, PSOProgramService.MSG_LINKPROGRAM_RESPONSE, 0, 0);
|
||||
Bundle params = new Bundle();
|
||||
//intent.setAction("com.epicgames.fortnite.OGLProgram");
|
||||
params.putByteArray(JobContext_Key, context);
|
||||
@@ -338,8 +402,8 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
|
||||
public void SendFail(Messenger replyTo, int ServiceID, int JobID, byte[] context, String FailMessage)
|
||||
{
|
||||
beginTrace("OGLProgramService.SendFail");
|
||||
Message msg = Message.obtain(null, OGLProgramService.MSG_LINKPROGRAM_RESPONSE, 0, 0);
|
||||
beginTrace("PSOProgramService.SendFail");
|
||||
Message msg = Message.obtain(null, PSOProgramService.MSG_LINKPROGRAM_RESPONSE, 0, 0);
|
||||
Bundle params = new Bundle();
|
||||
params.putByteArray(JobContext_Key, context);
|
||||
params.putInt(JobID_Key, JobID);
|
||||
@@ -358,6 +422,31 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
endTrace();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////// Vulkan context stuff
|
||||
public native void InitVKDevice();
|
||||
public native void ShutdownVKDevice();
|
||||
public native byte[] CompileVKGFXPSO(byte[] VertexShaderSource, byte[] PixelShaderSource, byte[] PSOData);
|
||||
|
||||
private void initVulkanContext()
|
||||
{
|
||||
beginTrace("PSOProgramService.InitVulkanContext");
|
||||
System.loadLibrary("psoservice");
|
||||
|
||||
InitVKDevice();
|
||||
endTrace();
|
||||
}
|
||||
|
||||
private byte[] compileVulkanPSO(int JobID, byte [] VertexShaderSource, byte [] PixelShaderSource, byte [] PSOData)
|
||||
{
|
||||
return CompileVKGFXPSO(VertexShaderSource, PixelShaderSource, PSOData);
|
||||
}
|
||||
|
||||
private void shutdownVulkanContext()
|
||||
{
|
||||
ShutdownVKDevice();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////// GL context stuff
|
||||
|
||||
private EGLDisplay mEglDisplay = EGL14.EGL_NO_DISPLAY;
|
||||
@@ -366,7 +455,7 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
|
||||
private void initGLContext()
|
||||
{
|
||||
beginTrace("OGLProgramService.InitContext");
|
||||
beginTrace("PSOProgramService.InitContext");
|
||||
mEglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
|
||||
//logger.verbose("2 mEglDisplay "+mEglDisplay.toString()+" err "+EGL14.eglGetError());
|
||||
int[] version = new int[2];
|
||||
@@ -451,7 +540,7 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
if( shader == 0 ) {
|
||||
throw new GLCompileException("Failed to create shader type: " + shaderType);
|
||||
}
|
||||
beginTrace("OGLProgramService.createShader "+shaderType);
|
||||
beginTrace("PSOProgramService.createShader "+shaderType);
|
||||
GLES31.glShaderSource(shader, source);
|
||||
//logger.debug("2 createShader err "+GLES31.glGetError());
|
||||
GLES31.glCompileShader(shader);
|
||||
@@ -498,7 +587,7 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
int mProgram = 0;
|
||||
|
||||
try {
|
||||
beginTrace("OGLProgramService.CompileAndLink "+JobID);
|
||||
beginTrace("PSOProgramService.CompileAndLink "+JobID);
|
||||
|
||||
mProgram = GLES31.glCreateProgram();
|
||||
if (mProgram <= 0) {
|
||||
@@ -521,7 +610,7 @@ public class OGLProgramService extends Service implements Logger.ILoggerCallback
|
||||
//logger.debug(JobID+" glAttachShader(cs) err "+GLES31.glGetError());
|
||||
}
|
||||
|
||||
beginTrace("OGLProgramService.CompileAndLink LINKING"+JobID);
|
||||
beginTrace("PSOProgramService.CompileAndLink LINKING"+JobID);
|
||||
GLES31.glLinkProgram(mProgram);
|
||||
endTrace();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.oglservices;
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -36,7 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class OGLProgramServiceAccessor
|
||||
public class PSOProgramServiceAccessor
|
||||
{
|
||||
static final boolean bEnableTrace = false;
|
||||
static void beginTrace(String msg)
|
||||
@@ -64,9 +64,20 @@ public class OGLProgramServiceAccessor
|
||||
,OGLProgramService6.class
|
||||
,OGLProgramService7.class
|
||||
};
|
||||
|
||||
static final Class<?>[] VulkanServiceClassTypes = new Class<?>[] {
|
||||
VulkanProgramService.class
|
||||
,VulkanProgramService1.class
|
||||
,VulkanProgramService2.class
|
||||
,VulkanProgramService3.class
|
||||
,VulkanProgramService4.class
|
||||
,VulkanProgramService5.class
|
||||
,VulkanProgramService6.class
|
||||
,VulkanProgramService7.class
|
||||
};
|
||||
|
||||
private static final String TAG = "OGLProgramServiceAccessor";
|
||||
private static OGLProgramServiceAccessor _OGLProgramServiceAccessor = null;
|
||||
private static final String TAG = "PSOProgramServiceAccessor";
|
||||
private static PSOProgramServiceAccessor _PSOProgramServiceAccessor = null;
|
||||
|
||||
OGLServiceInstance[] ServiceInstances;
|
||||
private GameActivity mContext;
|
||||
@@ -82,7 +93,7 @@ public class OGLProgramServiceAccessor
|
||||
private static final ConcurrentHashMap<Integer, JobResponse> SyncObs = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Handler for incoming messages from the OGLProgramService(s).
|
||||
* Handler for incoming messages from the PSOProgramService(s).
|
||||
*/
|
||||
static class IncomingHandler extends Handler
|
||||
{
|
||||
@@ -96,20 +107,20 @@ public class OGLProgramServiceAccessor
|
||||
{
|
||||
switch (msg.what)
|
||||
{
|
||||
case OGLProgramService.MSG_LINKPROGRAM_RESPONSE:
|
||||
case PSOProgramService.MSG_LINKPROGRAM_RESPONSE:
|
||||
{
|
||||
beginTrace("OGLProgramService.MSG_LINKPROGRAM_RESPONSE");
|
||||
byte[] CompiledResult = msg.getData().getByteArray(OGLProgramService.CompiledProgram_Key);
|
||||
byte[] JobContext = msg.getData().getByteArray(OGLProgramService.JobContext_Key);
|
||||
int JobID = msg.getData().getInt(OGLProgramService.JobID_Key, -1);
|
||||
int ServiceID = msg.getData().getInt(OGLProgramService.ServiceID_Key, -1);
|
||||
beginTrace("PSOProgramService.MSG_LINKPROGRAM_RESPONSE");
|
||||
byte[] CompiledResult = msg.getData().getByteArray(PSOProgramService.CompiledProgram_Key);
|
||||
byte[] JobContext = msg.getData().getByteArray(PSOProgramService.JobContext_Key);
|
||||
int JobID = msg.getData().getInt(PSOProgramService.JobID_Key, -1);
|
||||
int ServiceID = msg.getData().getInt(PSOProgramService.ServiceID_Key, -1);
|
||||
|
||||
try
|
||||
{
|
||||
ProgramServiceAccessorlock.readLock().lock();
|
||||
if (ServiceID >= 0 && ServiceID < _OGLProgramServiceAccessor.ServiceInstances.length)
|
||||
if (ServiceID >= 0 && ServiceID < _PSOProgramServiceAccessor.ServiceInstances.length)
|
||||
{
|
||||
_OGLProgramServiceAccessor.ServiceInstances[ServiceID].PendingJobs.decrementAndGet();
|
||||
_PSOProgramServiceAccessor.ServiceInstances[ServiceID].PendingJobs.decrementAndGet();
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -118,7 +129,7 @@ public class OGLProgramServiceAccessor
|
||||
}
|
||||
|
||||
{
|
||||
beginTrace("OGLProgramService.MSG_LINKPROGRAM_RESPONSE " + JobID);
|
||||
beginTrace("PSOProgramService.MSG_LINKPROGRAM_RESPONSE " + JobID);
|
||||
//Log.verbose("CompletedLinkBroadcastReceiver for job " + JobID + " program length " + (CompiledResult == null ? 0 : CompiledResult.length) + " context size " + (JobContext == null? 0 : JobContext.length));
|
||||
JobResponse response = SyncObs.get(JobID);
|
||||
if (response != null)
|
||||
@@ -144,7 +155,7 @@ public class OGLProgramServiceAccessor
|
||||
}
|
||||
}
|
||||
|
||||
static HandlerThread OGLProgramAccessorHandlerThread;
|
||||
static HandlerThread PSOProgramAccessorHandlerThread;
|
||||
|
||||
static Messenger mReplyToMe;
|
||||
|
||||
@@ -154,7 +165,7 @@ public class OGLProgramServiceAccessor
|
||||
|
||||
private static boolean IsNullOrEmpty(String string) { return string == null || string.isEmpty(); }
|
||||
|
||||
public OGLProgramServiceAccessor()
|
||||
public PSOProgramServiceAccessor()
|
||||
{
|
||||
//StrictMode.enableDefaults();
|
||||
//StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
|
||||
@@ -168,12 +179,12 @@ public class OGLProgramServiceAccessor
|
||||
{
|
||||
mContext = InContext;
|
||||
ClearServiceLogDirs();
|
||||
_OGLProgramServiceAccessor = this;
|
||||
_PSOProgramServiceAccessor = this;
|
||||
}
|
||||
|
||||
private void ClearServiceLogDirs()
|
||||
{
|
||||
String OGLLogDir = mContext.getFilesDir()+OGLProgramService.LogDir;
|
||||
String OGLLogDir = mContext.getFilesDir()+PSOProgramService.LogDir;
|
||||
File deleteDir = new File(OGLLogDir);
|
||||
boolean bDeleteDirExists = deleteDir.exists();
|
||||
if( bDeleteDirExists )
|
||||
@@ -190,19 +201,26 @@ public class OGLProgramServiceAccessor
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean AndroidThunkJava_StartOGLRemoteProgramLink(int numServices)
|
||||
public static boolean AndroidThunkJava_StartRemoteProgramLink(int numServices, boolean bUseVulkan)
|
||||
{
|
||||
boolean bSuccess = false;
|
||||
if( _OGLProgramServiceAccessor != null)
|
||||
if( _PSOProgramServiceAccessor != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProgramServiceAccessorlock.writeLock().lock();
|
||||
OGLProgramAccessorHandlerThread = new HandlerThread("OGLProgramAccessorThread");
|
||||
OGLProgramAccessorHandlerThread.start();
|
||||
mReplyToMe = new Messenger(new IncomingHandler(OGLProgramAccessorHandlerThread.getLooper()));
|
||||
PSOProgramAccessorHandlerThread = new HandlerThread("PSOProgramAccessorThread");
|
||||
PSOProgramAccessorHandlerThread.start();
|
||||
mReplyToMe = new Messenger(new IncomingHandler(PSOProgramAccessorHandlerThread.getLooper()));
|
||||
|
||||
bSuccess = _OGLProgramServiceAccessor.StartAndWaitForServices(numServices);
|
||||
if(bUseVulkan)
|
||||
{
|
||||
bSuccess = _PSOProgramServiceAccessor.StartAndWaitForVulkanServices(numServices);
|
||||
}
|
||||
else
|
||||
{
|
||||
bSuccess = _PSOProgramServiceAccessor.StartAndWaitForServices(numServices);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -216,20 +234,20 @@ public class OGLProgramServiceAccessor
|
||||
|
||||
if(!bSuccess)
|
||||
{
|
||||
AndroidThunkJava_StopOGLRemoteProgramLink();
|
||||
AndroidThunkJava_StopRemoteProgramLink();
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
public static void AndroidThunkJava_StopOGLRemoteProgramLink()
|
||||
public static void AndroidThunkJava_StopRemoteProgramLink()
|
||||
{
|
||||
if( _OGLProgramServiceAccessor != null)
|
||||
if( _PSOProgramServiceAccessor != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProgramServiceAccessorlock.writeLock().lock();
|
||||
_OGLProgramServiceAccessor.StopServices();
|
||||
OGLProgramAccessorHandlerThread.quitSafely();
|
||||
_PSOProgramServiceAccessor.StopServices();
|
||||
PSOProgramAccessorHandlerThread.quitSafely();
|
||||
mReplyToMe = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -261,6 +279,24 @@ public class OGLProgramServiceAccessor
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
boolean StartAndWaitForVulkanServices(int numServices)
|
||||
{
|
||||
numServices = Math.max(1, Math.min(numServices, VulkanServiceClassTypes.length));
|
||||
|
||||
ServiceInstances = new OGLServiceInstance[numServices];
|
||||
for(int i = 0; i< numServices ;i++)
|
||||
{
|
||||
ServiceInstances[i] = new OGLServiceInstance(VulkanServiceClassTypes[i]);
|
||||
}
|
||||
|
||||
boolean bSuccess = true;
|
||||
for (OGLServiceInstance ServiceInstance : ServiceInstances )
|
||||
{
|
||||
bSuccess = bSuccess && ServiceInstance.doBindAndWait();
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
void StopServices()
|
||||
{
|
||||
if(ServiceInstances != null)
|
||||
@@ -307,12 +343,12 @@ public class OGLProgramServiceAccessor
|
||||
try
|
||||
{
|
||||
ProgramServiceAccessorlock.readLock().lock();
|
||||
if (_OGLProgramServiceAccessor == null)
|
||||
if (_PSOProgramServiceAccessor == null)
|
||||
{
|
||||
Log.error("AndroidThunkJava_OGLRemoteProgramLink Called too early ");
|
||||
return null;
|
||||
}
|
||||
if (_OGLProgramServiceAccessor.ServiceInstances.length == 0)
|
||||
if (_PSOProgramServiceAccessor.ServiceInstances.length == 0)
|
||||
{
|
||||
Log.error( "AndroidThunkJava_OGLRemoteProgramLink not enabled.");
|
||||
return null;
|
||||
@@ -320,7 +356,7 @@ public class OGLProgramServiceAccessor
|
||||
|
||||
int ThisJobID = JobID.incrementAndGet();
|
||||
beginTrace("AndroidThunkJava_OGLRemoteProgramLink " + ThisJobID);
|
||||
Message msg = Message.obtain(null, OGLProgramService.MSG_LINKPROGRAM, 0, 0);
|
||||
Message msg = Message.obtain(null, PSOProgramService.MSG_LINKPROGRAM, 0, 0);
|
||||
Bundle params = new Bundle();
|
||||
if (IsNullOrEmpty(ComputeShader))
|
||||
{
|
||||
@@ -335,18 +371,18 @@ public class OGLProgramServiceAccessor
|
||||
Log.error("Failed to send compile job PS is null ");
|
||||
return null;
|
||||
}
|
||||
params.putString(OGLProgramService.VS_Key, VertexShader);
|
||||
params.putString(OGLProgramService.PS_Key, PixelShader);
|
||||
params.putString(PSOProgramService.VS_Key, VertexShader);
|
||||
params.putString(PSOProgramService.PS_Key, PixelShader);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Log.verbose("Compute compile job");
|
||||
params.putString(OGLProgramService.CS_Key, ComputeShader);
|
||||
params.putString(PSOProgramService.CS_Key, ComputeShader);
|
||||
}
|
||||
|
||||
params.putByteArray(OGLProgramService.JobContext_Key, ContextData);
|
||||
params.putByteArray(PSOProgramService.JobContext_Key, ContextData);
|
||||
|
||||
params.putInt(OGLProgramService.JobID_Key, ThisJobID);
|
||||
params.putInt(PSOProgramService.JobID_Key, ThisJobID);
|
||||
msg.replyTo = mReplyToMe;
|
||||
|
||||
JobResponse pendingResponse = new JobResponse();
|
||||
@@ -358,15 +394,15 @@ public class OGLProgramServiceAccessor
|
||||
boolean bValidService = false;
|
||||
OGLServiceInstance thisInstance = null;
|
||||
// loop through the services to find a valid (bound) service, skip and attempt to rebind any unbound services.
|
||||
for(int i = 0; i<_OGLProgramServiceAccessor.ServiceInstances.length; i++)
|
||||
for(int i = 0; i<_PSOProgramServiceAccessor.ServiceInstances.length; i++)
|
||||
{
|
||||
int ServiceIdx = _OGLProgramServiceAccessor.LastServiceIdx.incrementAndGet() % _OGLProgramServiceAccessor.ServiceInstances.length;
|
||||
OGLServiceInstance testInstance = _OGLProgramServiceAccessor.ServiceInstances[ServiceIdx];
|
||||
int ServiceIdx = _PSOProgramServiceAccessor.LastServiceIdx.incrementAndGet() % _PSOProgramServiceAccessor.ServiceInstances.length;
|
||||
OGLServiceInstance testInstance = _PSOProgramServiceAccessor.ServiceInstances[ServiceIdx];
|
||||
if(testInstance.IsServiceBound())
|
||||
{
|
||||
// found a valid service.
|
||||
thisInstance = testInstance;
|
||||
params.putInt(OGLProgramService.ServiceID_Key, ServiceIdx);
|
||||
params.putInt(PSOProgramService.ServiceID_Key, ServiceIdx);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -427,14 +463,176 @@ public class OGLProgramServiceAccessor
|
||||
|
||||
SyncObs.remove(ThisJobID);
|
||||
|
||||
byte[] EngineJobContext = pendingResponse.data.getByteArray(OGLProgramService.JobContext_Key);
|
||||
byte[] CompiledBinary = pendingResponse.data.getByteArray(OGLProgramService.CompiledProgram_Key);
|
||||
int JobID = pendingResponse.data.getInt(OGLProgramService.JobID_Key);
|
||||
byte[] EngineJobContext = pendingResponse.data.getByteArray(PSOProgramService.JobContext_Key);
|
||||
byte[] CompiledBinary = pendingResponse.data.getByteArray(PSOProgramService.CompiledProgram_Key);
|
||||
int JobID = pendingResponse.data.getInt(PSOProgramService.JobID_Key);
|
||||
|
||||
//Log.verbose("OGLRemoteProgramLink handoff ("+JobID+"), ("+(EngineJobContext == null ? 0 : EngineJobContext.length)+", "+(CompiledBinary==null?0:CompiledBinary.length)+")");
|
||||
|
||||
JNIProgramLinkResponse jniResponse = new JNIProgramLinkResponse();
|
||||
String fail = pendingResponse.data.getString(OGLProgramService.JobFail);
|
||||
String fail = pendingResponse.data.getString(PSOProgramService.JobFail);
|
||||
jniResponse.bCompileSuccess = fail == null || fail.isEmpty();
|
||||
jniResponse.ErrorMessage = fail;
|
||||
jniResponse.CompiledProgram = CompiledBinary;
|
||||
|
||||
return jniResponse;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.error( "OGLRemoteProgramLink FAIL " + e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ProgramServiceAccessorlock.readLock().unlock();
|
||||
endTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JNIProgramLinkResponse AndroidThunkJava_VKPSOGFXCompile(byte[] ContextData, byte[] VertexShader, byte[] PixelShader, byte[] PSOData)
|
||||
{
|
||||
if(GameActivity.IsActivityPaused())
|
||||
{
|
||||
// one at a time when backgrounded.
|
||||
synchronized (ProgramLinkLock)
|
||||
{
|
||||
return VKPSOGFXCompile_internal(ContextData, VertexShader, PixelShader, PSOData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return VKPSOGFXCompile_internal(ContextData, VertexShader, PixelShader, PSOData);
|
||||
}
|
||||
}
|
||||
|
||||
private static JNIProgramLinkResponse VKPSOGFXCompile_internal(byte[] ContextData, byte[] VertexShader, byte[] PixelShader, byte[] PSOData)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProgramServiceAccessorlock.readLock().lock();
|
||||
if (_PSOProgramServiceAccessor == null)
|
||||
{
|
||||
Log.error("AndroidThunkJava_VKPSOGFXCompile Called too early ");
|
||||
return null;
|
||||
}
|
||||
if (_PSOProgramServiceAccessor.ServiceInstances.length == 0)
|
||||
{
|
||||
Log.error( "AndroidThunkJava_VKPSOGFXCompile not enabled.");
|
||||
return null;
|
||||
}
|
||||
|
||||
int ThisJobID = JobID.incrementAndGet();
|
||||
beginTrace("AndroidThunkJava_OGLRemoteProgramLink " + ThisJobID);
|
||||
Message msg = Message.obtain(null, PSOProgramService.MSG_LINKPROGRAM, 0, 0);
|
||||
Bundle params = new Bundle();
|
||||
|
||||
//Log.verbose("GFX compile job");
|
||||
if (VertexShader.length == 0)
|
||||
{
|
||||
Log.error("Failed to send compile job VS is null ");
|
||||
return null;
|
||||
}
|
||||
if (PixelShader.length == 0)
|
||||
{
|
||||
Log.error("Failed to send compile job PS is null ");
|
||||
return null;
|
||||
}
|
||||
params.putByteArray(PSOProgramService.VS_Key, VertexShader);
|
||||
params.putByteArray(PSOProgramService.PS_Key, PixelShader);
|
||||
params.putByteArray(PSOProgramService.PSOData_Key, PSOData);
|
||||
|
||||
params.putByteArray(PSOProgramService.JobContext_Key, ContextData);
|
||||
|
||||
params.putInt(PSOProgramService.JobID_Key, ThisJobID);
|
||||
msg.replyTo = mReplyToMe;
|
||||
|
||||
JobResponse pendingResponse = new JobResponse();
|
||||
synchronized (pendingResponse.SyncObj)
|
||||
{
|
||||
SyncObs.put(ThisJobID, pendingResponse);
|
||||
|
||||
msg.setData(params);
|
||||
boolean bValidService = false;
|
||||
OGLServiceInstance thisInstance = null;
|
||||
// loop through the services to find a valid (bound) service, skip and attempt to rebind any unbound services.
|
||||
for(int i = 0; i<_PSOProgramServiceAccessor.ServiceInstances.length; i++)
|
||||
{
|
||||
int ServiceIdx = _PSOProgramServiceAccessor.LastServiceIdx.incrementAndGet() % _PSOProgramServiceAccessor.ServiceInstances.length;
|
||||
OGLServiceInstance testInstance = _PSOProgramServiceAccessor.ServiceInstances[ServiceIdx];
|
||||
if(testInstance.IsServiceBound())
|
||||
{
|
||||
// found a valid service.
|
||||
thisInstance = testInstance;
|
||||
params.putInt(PSOProgramService.ServiceID_Key, ServiceIdx);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// found an unbound service, attempt to rebind and continue;
|
||||
Log.warn("OGLRemoteProgramLink "+testInstance.Name()+" (" + ThisJobID + ") was unbound, rebinding and trying next service");
|
||||
testInstance.doBindService();
|
||||
testInstance.ReadBackServiceLog();
|
||||
}
|
||||
}
|
||||
|
||||
//Log.verbose("OGLRemoteProgramLink dispatching to "+thisInstance.Name()+" (" + ThisJobID + ")");
|
||||
pendingResponse.ResponseState = JobResponse.ResponseStateEnum.Pending;
|
||||
if( thisInstance != null && thisInstance.SendMessage(msg) )
|
||||
{
|
||||
int pendingJobs = thisInstance.PendingJobs.incrementAndGet();
|
||||
|
||||
long tStartTime = System.nanoTime();
|
||||
// wait for 10s before giving up on the compile job.
|
||||
long tTimeoutInMS = 10000;
|
||||
|
||||
while (pendingResponse.ResponseState != JobResponse.ResponseStateEnum.Responded)
|
||||
{
|
||||
// we must loop as waits can randomly wake.
|
||||
pendingResponse.SyncObj.wait(1000);
|
||||
|
||||
if ((System.nanoTime() - tStartTime) >= (tTimeoutInMS * 1000000))
|
||||
{
|
||||
Log.error("OGLRemoteProgramLink TIMED OUT WAITING " + ThisJobID + " for " + (System.nanoTime() - tStartTime) / 1000000 + "ms. pending tasks "+thisInstance.PendingJobs.get());
|
||||
//timeout
|
||||
SyncObs.remove(ThisJobID);
|
||||
thisInstance.ReadBackServiceLog();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
long totalWaitTimeMS = (System.nanoTime() - tStartTime) / 1000000;
|
||||
if(totalWaitTimeMS > 2500)
|
||||
{
|
||||
Log.verbose("OGLRemoteProgramLink responded " + ThisJobID + " total wait time "+totalWaitTimeMS+" ms. pending tasks "+thisInstance.PendingJobs.get());
|
||||
}
|
||||
}
|
||||
else if( thisInstance != null)
|
||||
{
|
||||
// process communications failed somehow.
|
||||
SyncObs.remove(ThisJobID);
|
||||
thisInstance.ReadBackServiceLog();
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to find a single bound service?
|
||||
Log.error("OGLRemoteProgramLink " + ThisJobID + " no valid bound services.");
|
||||
SyncObs.remove(ThisJobID);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SyncObs.remove(ThisJobID);
|
||||
|
||||
byte[] EngineJobContext = pendingResponse.data.getByteArray(PSOProgramService.JobContext_Key);
|
||||
byte[] CompiledBinary = pendingResponse.data.getByteArray(PSOProgramService.CompiledProgram_Key);
|
||||
int JobID = pendingResponse.data.getInt(PSOProgramService.JobID_Key);
|
||||
|
||||
//Log.verbose("OGLRemoteProgramLink handoff ("+JobID+"), ("+(EngineJobContext == null ? 0 : EngineJobContext.length)+", "+(CompiledBinary==null?0:CompiledBinary.length)+")");
|
||||
|
||||
JNIProgramLinkResponse jniResponse = new JNIProgramLinkResponse();
|
||||
String fail = pendingResponse.data.getString(PSOProgramService.JobFail);
|
||||
jniResponse.bCompileSuccess = fail == null || fail.isEmpty();
|
||||
jniResponse.ErrorMessage = fail;
|
||||
jniResponse.CompiledProgram = CompiledBinary;
|
||||
@@ -477,7 +675,7 @@ public class OGLProgramServiceAccessor
|
||||
// Opens the log file(s) for the service, scans each entry and prints any new entries.
|
||||
synchronized void ReadBackServiceLog()
|
||||
{
|
||||
String OGLLogDirPath = mContext.getFilesDir()+OGLProgramService.LogDir;
|
||||
String OGLLogDirPath = mContext.getFilesDir()+PSOProgramService.LogDir;
|
||||
File OGLLogDir = new File(OGLLogDirPath);
|
||||
File[] LogFiles = OGLLogDir.listFiles();
|
||||
if( LogFiles == null)
|
||||
@@ -530,9 +728,9 @@ public class OGLProgramServiceAccessor
|
||||
/**
|
||||
* Defines callbacks for service binding, passed to bindService()
|
||||
*/
|
||||
private final OGLProgramServiceConnection mConnection = new OGLProgramServiceConnection();
|
||||
private final PSOProgramServiceConnection mConnection = new PSOProgramServiceConnection();
|
||||
|
||||
class OGLProgramServiceConnection implements ServiceConnection
|
||||
class PSOProgramServiceConnection implements ServiceConnection
|
||||
{
|
||||
public final Object mConnectionSync = new Object();
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class VulkanProgramService extends PSOProgramService
|
||||
{
|
||||
@Override
|
||||
public boolean UseVulkan() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
package com.epicgames.unreal.psoservices;
|
||||
|
||||
public class VulkanProgramService1 extends VulkanProgramService
|
||||
{
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user