Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REG-2176] Skip graphics capture if graphics not available #354

Merged
merged 7 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -290,82 +290,102 @@ private IEnumerator UpdateGPUData(int frame, Action<(byte[], int, int)?> onCompl
}
}
}

// wait for end of frame or graphics data will be incorrect
yield return new WaitForEndOfFrame();

// get this in there so we don't get duplicate requests out for the same frame
if (GPUReadbackRequests.TryAdd(frame, null))

// If we are running in -nographics mode, the async task fails, causing an exception inside
// the AsyncGPUReadback.Request that is difficult to catch. This ensures that the screenshot
// is only taken when we have graphics
if (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Null)
nAmKcAz marked this conversation as resolved.
Show resolved Hide resolved
{
var screenWidth = Screen.width;
var screenHeight = Screen.height;

if (_screenShotTexture == null || _screenShotTexture.width != screenWidth || _screenShotTexture.height != screenHeight)
// wait for end of frame or graphics data will be incorrect
yield return new WaitForEndOfFrame();

// get this in there so we don't get duplicate requests out for the same frame
if (GPUReadbackRequests.TryAdd(frame, null))
{
if (_screenShotTexture != null)
{
Object.Destroy(_screenShotTexture);
}
var screenWidth = Screen.width;
var screenHeight = Screen.height;

if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
{
// why Metal defaults to B8G8R8A8_SRGB and thus flips the colors.. who knows..
// this setting stops it from spamming log errors
_screenShotTexture = new RenderTexture(screenWidth, screenHeight, 0, GraphicsFormat.R8G8B8A8_SRGB);
}
else
if (_screenShotTexture == null || _screenShotTexture.width != screenWidth ||
_screenShotTexture.height != screenHeight)
{
_screenShotTexture = new RenderTexture(screenWidth, screenHeight, 0);
if (_screenShotTexture != null)
{
Object.Destroy(_screenShotTexture);
}

if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
{
// why Metal defaults to B8G8R8A8_SRGB and thus flips the colors.. who knows..
// this setting stops it from spamming log errors
_screenShotTexture = new RenderTexture(screenWidth, screenHeight, 0,
GraphicsFormat.R8G8B8A8_SRGB);
}
else
{
_screenShotTexture = new RenderTexture(screenWidth, screenHeight, 0);
}
}
}

var theGraphicsFormat = _screenShotTexture.graphicsFormat;
var theGraphicsFormat = _screenShotTexture.graphicsFormat;

try
{
ScreenCapture.CaptureScreenshotIntoRenderTexture(_screenShotTexture);
var readbackRequest = AsyncGPUReadback.Request(_screenShotTexture, 0, GraphicsFormat.R8G8B8A8_SRGB, request =>
try
{
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)
ScreenCapture.CaptureScreenshotIntoRenderTexture(_screenShotTexture);
var readbackRequest = AsyncGPUReadback.Request(_screenShotTexture, 0,
GraphicsFormat.R8G8B8A8_SRGB, request =>
{
// 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++)
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)
{
// 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);

RGDebug.LogDebug($"ScreenshotCapture - Captured screenshot for frame # {frame}");
AddFrame(frame, (imageOutput.ToArray(), screenWidth, screenHeight));
}
else
{
// 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);
RGDebug.LogWarning(
$"ScreenshotCapture - Error capturing screenshot for frame # {frame}");
AddFrame(frame, null);
}
} //else.. we're fine

var imageOutput = ImageConversion.EncodeNativeArrayToJPG(pixels, theGraphicsFormat, (uint)screenWidth, (uint)screenHeight);
HandleCompletedActionCallbacks();
});
// update from null to the real request
GPUReadbackRequests[frame] = readbackRequest;

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;
}
catch (Exception e)
{
RGDebug.LogWarning(
$"ScreenshotCapture - Exception starting to capture screenshot for frame # {frame} - {e.Message}");
}

}
catch (Exception e)
{
RGDebug.LogWarning($"ScreenshotCapture - Exception starting to capture screenshot for frame # {frame} - {e.Message}");
}
}
}

Expand Down
Loading