Avoid zealously copying the entire video buffer
this might be larger than bufferwidth*bufferheight, and thus possibly dramantically decrease screenshot/dumping performance
This commit is contained in:
parent
57e3c47bcc
commit
d8431d615e
|
@ -187,7 +187,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (src.BufferWidth == dst.BufferWidth && src.BufferHeight == dst.BufferHeight)
|
||||
{
|
||||
Array.Copy(src.GetVideoBuffer(), dst.GetVideoBuffer(), src.GetVideoBuffer().Length);
|
||||
Array.Copy(src.GetVideoBuffer(), dst.GetVideoBuffer(), src.BufferWidth * src.BufferHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -70,31 +70,19 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (config.SaveScreenshot && _videoProvider != null)
|
||||
{
|
||||
var buff = _videoProvider.GetVideoBuffer();
|
||||
if (buff.Length == 1)
|
||||
var outWidth = _videoProvider.BufferWidth;
|
||||
var outHeight = _videoProvider.BufferHeight;
|
||||
|
||||
// if buffer is too big, scale down screenshot
|
||||
if (!config.NoLowResLargeScreenshots && outWidth * outHeight >= config.BigScreenshotSize)
|
||||
{
|
||||
// is a hacky opengl texture ID. can't handle this now!
|
||||
// need to discuss options
|
||||
// 1. cores must be able to provide a pixels VideoProvider in addition to a texture ID, on command (not very hard overall but interface changing and work per core)
|
||||
// 2. SavestateManager must be setup with a mechanism for resolving texture IDs (even less work, but sloppy)
|
||||
// There are additional problems with AVWriting. They depend on VideoProvider providing pixels.
|
||||
outWidth /= 2;
|
||||
outHeight /= 2;
|
||||
}
|
||||
else
|
||||
|
||||
using (new SimpleTime("Save Framebuffer"))
|
||||
{
|
||||
int outWidth = _videoProvider.BufferWidth;
|
||||
int outHeight = _videoProvider.BufferHeight;
|
||||
|
||||
// if buffer is too big, scale down screenshot
|
||||
if (!config.NoLowResLargeScreenshots && buff.Length >= config.BigScreenshotSize)
|
||||
{
|
||||
outWidth /= 2;
|
||||
outHeight /= 2;
|
||||
}
|
||||
|
||||
using (new SimpleTime("Save Framebuffer"))
|
||||
{
|
||||
bs.PutLump(BinaryStateLump.Framebuffer, s => QuickBmpFile.Save(_videoProvider, s, outWidth, outHeight));
|
||||
}
|
||||
bs.PutLump(BinaryStateLump.Framebuffer, s => QuickBmpFile.Save(_videoProvider, s, outWidth, outHeight));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,13 +210,13 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch
|
||||
{
|
||||
var buff = videoProvider.GetVideoBuffer();
|
||||
var vb = videoProvider.GetVideoBuffer();
|
||||
var vbLen = videoProvider.BufferWidth * videoProvider.BufferHeight;
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < buff.Length; i++)
|
||||
for (var i = 0; i < vbLen; i++)
|
||||
{
|
||||
int j = br.ReadInt32();
|
||||
buff[i] = j;
|
||||
vb[i] = br.ReadInt32();
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
public VideoCopy(IVideoProvider c)
|
||||
{
|
||||
_vb = (int[])c.GetVideoBuffer().Clone();
|
||||
_vb = c.GetVideoBufferCopy();
|
||||
BufferWidth = c.BufferWidth;
|
||||
BufferHeight = c.BufferHeight;
|
||||
BackgroundColor = c.BackgroundColor;
|
||||
|
|
|
@ -195,7 +195,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
var video = source.GetVideoBuffer();
|
||||
try
|
||||
{
|
||||
_muxer.WriteVideoFrame(video);
|
||||
_muxer.WriteVideoFrame(video.AsSpan(0, _width * _height));
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
|
@ -538,15 +539,15 @@ namespace BizHawk.Client.EmuHawk
|
|||
/// <param name="video">raw video data; if length 0, write EOR</param>
|
||||
/// <exception cref="Exception">internal error, possible A/V desync</exception>
|
||||
/// <exception cref="InvalidOperationException">already written EOR</exception>
|
||||
public void WriteVideoFrame(int[] video)
|
||||
public void WriteVideoFrame(ReadOnlySpan<int> video)
|
||||
{
|
||||
if (_videoDone)
|
||||
throw new InvalidOperationException("Can't write data after end of relevance!");
|
||||
if (_audioQueue.Count > 5)
|
||||
throw new Exception("A/V Desync?");
|
||||
int dataLen = video.Length * sizeof(int);
|
||||
byte[] data = _bufferPool.GetBufferAtLeast(dataLen);
|
||||
Buffer.BlockCopy(video, 0, data, 0, dataLen);
|
||||
var dataLen = video.Length * sizeof(int);
|
||||
var data = _bufferPool.GetBufferAtLeast(dataLen);
|
||||
MemoryMarshal.AsBytes(video).CopyTo(data.AsSpan(0, dataLen));
|
||||
if (dataLen == 0)
|
||||
{
|
||||
_videoDone = true;
|
||||
|
@ -643,12 +644,12 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
if (!_videoDone)
|
||||
{
|
||||
WriteVideoFrame(Array.Empty<int>());
|
||||
WriteVideoFrame([ ]);
|
||||
}
|
||||
|
||||
if (!_audioDone)
|
||||
{
|
||||
WriteAudioFrame(Array.Empty<short>());
|
||||
WriteAudioFrame([ ]);
|
||||
}
|
||||
|
||||
// flush any remaining queued packets
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
SetVideoParameters(source.BufferWidth, source.BufferHeight);
|
||||
}
|
||||
|
||||
_current.WriteVideoFrame(source.GetVideoBuffer());
|
||||
_current.WriteVideoFrame(source.GetVideoBuffer().AsSpan(0, _width * _height));
|
||||
}
|
||||
|
||||
public void AddSamples(short[] samples)
|
||||
|
|
|
@ -2458,7 +2458,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
public BitmapBuffer MakeScreenshotImage()
|
||||
{
|
||||
var ret = new BitmapBuffer(_currentVideoProvider.BufferWidth, _currentVideoProvider.BufferHeight, _currentVideoProvider.GetVideoBuffer().ToArray());
|
||||
var ret = new BitmapBuffer(_currentVideoProvider.BufferWidth, _currentVideoProvider.BufferHeight, _currentVideoProvider.GetVideoBufferCopy());
|
||||
ret.DiscardAlpha();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -250,7 +250,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
movieToRecord.SavestateFramebuffer = Array.Empty<int>();
|
||||
if (_emulator.HasVideoProvider())
|
||||
{
|
||||
movieToRecord.SavestateFramebuffer = (int[])_emulator.AsVideoProvider().GetVideoBuffer().Clone();
|
||||
movieToRecord.SavestateFramebuffer = _emulator.AsVideoProvider().GetVideoBufferCopy();
|
||||
}
|
||||
}
|
||||
else if (StartFromCombo.SelectedItem.ToString() is START_FROM_SAVERAM && _emulator.HasSaveRam())
|
||||
|
|
|
@ -10,6 +10,9 @@ namespace BizHawk.Emulation.Common
|
|||
{
|
||||
/// <summary>
|
||||
/// Returns a frame buffer of the current video content
|
||||
/// This might be a reference to a stored frame buffer
|
||||
/// Only <see cref="BufferWidth"/> * <see cref="BufferHeight"/> pixels valid
|
||||
/// (The buffer might be larger than such, so don't rely on <see cref="Array.Length"/>
|
||||
/// </summary>
|
||||
int[] GetVideoBuffer();
|
||||
|
||||
|
@ -81,5 +84,19 @@ namespace BizHawk.Emulation.Common
|
|||
b2[i] = b1[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains a copy of the video buffer
|
||||
/// <see cref="IVideoProvider.GetVideoBuffer" /> may return a reference
|
||||
/// and might be much larger than the reported <see cref="IVideoProvider.BufferWidth"/> * <see cref="IVideoProvider.BufferHeight"/> (to account for differing frame sizes)
|
||||
/// so this should be used to get an explicit copy
|
||||
/// </summary>
|
||||
public static int[] GetVideoBufferCopy(this IVideoProvider videoProvider)
|
||||
{
|
||||
var vb = videoProvider.GetVideoBuffer();
|
||||
var ret = new int[videoProvider.BufferWidth * videoProvider.BufferHeight];
|
||||
vb.AsSpan(0, ret.Length).CopyTo(ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue