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:
jeannoe morissette
2022-08-22 21:18:17 -04:00
parent a2fb924c1f
commit 7ebedb9384
47 changed files with 2641 additions and 461 deletions

View File

@@ -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!");
}

View File

@@ -1,8 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.oglservices;
public class OGLProgramService1 extends OGLProgramService
{
}

View File

@@ -1,8 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.oglservices;
public class OGLProgramService2 extends OGLProgramService
{
}

View File

@@ -1,8 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.oglservices;
public class OGLProgramService3 extends OGLProgramService
{
}

View File

@@ -1,8 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.oglservices;
public class OGLProgramService4 extends OGLProgramService
{
}

View File

@@ -1,8 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.oglservices;
public class OGLProgramService5 extends OGLProgramService
{
}

View File

@@ -1,8 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.oglservices;
public class OGLProgramService6 extends OGLProgramService
{
}

View File

@@ -1,8 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.oglservices;
public class OGLProgramService7 extends OGLProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService extends PSOProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService1 extends PSOProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService2 extends PSOProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService3 extends PSOProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService4 extends PSOProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService5 extends PSOProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService6 extends PSOProgramService
{
}

View File

@@ -0,0 +1,8 @@
// Copyright Epic Games, Inc. All Rights Reserved.
package com.epicgames.unreal.psoservices;
public class OGLProgramService7 extends PSOProgramService
{
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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