Skip to content

Commit

Permalink
[REG-2176] Skip graphics capture if graphics not available (#354)
Browse files Browse the repository at this point in the history
  • Loading branch information
vontell authored Nov 26, 2024
1 parent f6ca99a commit c15a2ce
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ private static RenderTexture GetRenderTexture()

private void UpdateGameFacePixelHash()
{
if (_isActive)
// If we are running in -nographics mode, the async task below fails, causing an exception inside
// the AsyncGPUReadback.Request that is difficult to catch. This ensures that the image data
// is only read when we have graphics
if (_isActive && SystemInfo.graphicsDeviceType != GraphicsDeviceType.Null)
{
// have to re-get this every time because it changes on resolution and other screen changes that update the gameface render target
var cohtmlViewTexture = GetRenderTexture();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,24 @@ public void WaitForCompletion()
}

/**
* <summary>Calls the onSuccess callback when the readback request finishes or if data is already available</summary>
* <summary>
* Calls the onSuccess callback when the readback request finishes or if data is already available.
* If the system is running in a no graphics mode, this will instead just immediately complete the
* action.
* </summary>
*/
public void GetCurrentScreenshotWithCallback(long segmentNumber, Action<(byte[], int, int)?> onCompletion)
{

// When we don't have graphics available, we immediate invoke the callback with a null value. With how
// we use this function now, this needs to happen so the tick data writing task correctly saves the
// resulting data.
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null && onCompletion != null)
{
onCompletion.Invoke(null);
return;
}

var frame = UnityEngine.Time.frameCount;
lock (SyncLock)
{
Expand Down Expand Up @@ -325,39 +339,39 @@ private IEnumerator UpdateGPUData(int frame, Action<(byte[], int, int)?> onCompl
{
ScreenCapture.CaptureScreenshotIntoRenderTexture(_screenShotTexture);
var readbackRequest = AsyncGPUReadback.Request(_screenShotTexture, 0, GraphicsFormat.R8G8B8A8_SRGB, request =>
{
if (!request.hasError)
{
var pixels = request.GetData<Color32>();
var copyBuffer = _copyBuffer.Value; // uses a threadlocal to avoid re-allocating this on every readback
if (SystemInfo.graphicsUVStartsAtTop)
if (!request.hasError)
{
// the pixels from the GPU are upside down, we need to reverse this for it to be right side up
var halfHeight = screenHeight / 2;
for (var i = 0; i <= halfHeight; i++)
var pixels = request.GetData<Color32>();
var copyBuffer = _copyBuffer.Value; // uses a threadlocal to avoid re-allocating this on every readback
if (SystemInfo.graphicsUVStartsAtTop)
{
// swap rows
// bottom row to buffer
NativeArray<Color32>.Copy(pixels, i * screenWidth, copyBuffer, 0, screenWidth);
// top row to bottom
NativeArray<Color32>.Copy(pixels, (screenHeight - i - 1) * screenWidth, pixels, i * screenWidth, screenWidth);
// buffer to top row
NativeArray<Color32>.Copy(copyBuffer, 0, pixels, (screenHeight - i - 1) * screenWidth, screenWidth);
}
} //else.. we're fine
// the pixels from the GPU are upside down, we need to reverse this for it to be right side up
var halfHeight = screenHeight / 2;
for (var i = 0; i <= halfHeight; i++)
{
// swap rows
// bottom row to buffer
NativeArray<Color32>.Copy(pixels, i * screenWidth, copyBuffer, 0, screenWidth);
// top row to bottom
NativeArray<Color32>.Copy(pixels, (screenHeight - i - 1) * screenWidth, pixels, i * screenWidth, screenWidth);
// buffer to top row
NativeArray<Color32>.Copy(copyBuffer, 0, pixels, (screenHeight - i - 1) * screenWidth, screenWidth);
}
} //else.. we're fine

var imageOutput = ImageConversion.EncodeNativeArrayToJPG(pixels, theGraphicsFormat, (uint)screenWidth, (uint)screenHeight);
var imageOutput = ImageConversion.EncodeNativeArrayToJPG(pixels, theGraphicsFormat, (uint)screenWidth, (uint)screenHeight);

RGDebug.LogDebug($"ScreenshotCapture - Captured screenshot for frame # {frame}");
AddFrame(frame, (imageOutput.ToArray(), screenWidth, screenHeight));
}
else
{
RGDebug.LogWarning($"ScreenshotCapture - Error capturing screenshot for frame # {frame}");
AddFrame(frame, null);
}
HandleCompletedActionCallbacks();
});
RGDebug.LogDebug($"ScreenshotCapture - Captured screenshot for frame # {frame}");
AddFrame(frame, (imageOutput.ToArray(), screenWidth, screenHeight));
}
else
{
RGDebug.LogWarning($"ScreenshotCapture - Error capturing screenshot for frame # {frame}");
AddFrame(frame, null);
}
HandleCompletedActionCallbacks();
});
// update from null to the real request
GPUReadbackRequests[frame] = readbackRequest;

Expand Down

0 comments on commit c15a2ce

Please sign in to comment.