[host] improve capture performance

Contrary to the MS documentation, benchmarking shows a substantial
increase in performance when releasing the captured frame as soon
as possible. This change makes it possible to achieve 60FPS at 4K
resolutions.
This commit is contained in:
Geoffrey McRae 2018-05-31 18:51:28 +10:00
parent 3f331f2e62
commit d4c41d2d94
3 changed files with 42 additions and 35 deletions

View file

@ -435,11 +435,7 @@ void DXGI::DeInitialize()
m_mfTransform->DeleteInputStream(0);
}
if (m_releaseFrame)
{
m_releaseFrame = false;
m_dup->ReleaseFrame();
}
ReleaseFrame();
if (m_pointer)
{
@ -611,26 +607,6 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
{
while (true)
{
if (m_releaseFrame)
{
m_releaseFrame = false;
status = m_dup->ReleaseFrame();
switch (status)
{
case S_OK:
break;
case DXGI_ERROR_INVALID_CALL:
DEBUG_ERROR("Frame was already released");
return GRAB_STATUS_ERROR;
case DXGI_ERROR_ACCESS_LOST:
WaitForDesktop();
return GRAB_STATUS_REINIT;
}
}
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
if (status == DXGI_ERROR_WAIT_TIMEOUT)
{
@ -745,6 +721,7 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
if (!texture)
{
ReleaseFrame();
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
return GRAB_STATUS_ERROR;
}
@ -752,6 +729,30 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
return GRAB_STATUS_OK;
}
GrabStatus Capture::DXGI::ReleaseFrame()
{
if (!m_releaseFrame)
return GRAB_STATUS_OK;
m_releaseFrame = false;
switch (m_dup->ReleaseFrame())
{
case S_OK:
break;
case DXGI_ERROR_INVALID_CALL:
DEBUG_ERROR("Frame was already released");
return GRAB_STATUS_ERROR;
case WAIT_ABANDONED:
case DXGI_ERROR_ACCESS_LOST:
WaitForDesktop();
return GRAB_STATUS_REINIT;
}
return GRAB_STATUS_OK;
}
GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cursor)
{
GrabStatus result;
@ -762,7 +763,10 @@ GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cu
{
result = GrabFrameTexture(frame, cursor, src, timeout);
if (result != GRAB_STATUS_OK)
{
ReleaseFrame();
return result;
}
if (timeout)
{
@ -785,6 +789,10 @@ GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cu
m_deviceContext->CopyResource(m_texture, src);
SafeRelease(&src);
result = ReleaseFrame();
if (result != GRAB_STATUS_OK)
return result;
if (m_surfaceMapped)
{
m_deviceContext->Unmap(m_texture, 0);
@ -855,6 +863,7 @@ GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorI
result = GrabFrameTexture(frame, cursor, src, timeout);
if (result != GRAB_STATUS_OK)
{
ReleaseFrame();
return result;
}
@ -898,6 +907,7 @@ GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorI
SafeRelease(&sample);
SafeRelease(&buffer);
ReleaseFrame();
EnterCriticalSection(&m_encodeCS);
}

View file

@ -117,6 +117,7 @@ namespace Capture
bool InitH264Capture();
GrabStatus GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout);
GrabStatus ReleaseFrame();
GrabStatus GrabFrameRaw (struct FrameInfo & frame, struct CursorInfo & cursor);
GrabStatus GrabFrameH264 (struct FrameInfo & frame, struct CursorInfo & cursor);

View file

@ -157,6 +157,10 @@ void Service::DeInitialize()
m_cursorDataSize = 0;
m_frameSize = 0;
WaitForSingleObject(m_cursorThread, INFINITE);
CloseHandle(m_cursorThread);
CloseHandle(m_cursorEvent);
m_ivshmem->DeInitialize();
if (m_capture)
@ -165,10 +169,6 @@ void Service::DeInitialize()
m_capture = NULL;
}
WaitForSingleObject(m_cursorThread, INFINITE);
CloseHandle(m_cursorThread);
CloseHandle(m_cursorEvent );
m_memory = NULL;
m_initialized = false;
}
@ -213,10 +213,8 @@ bool Service::Process()
Sleep(2);
}
struct FrameInfo frame;
struct CursorInfo cursor;
ZeroMemory(&frame , sizeof(struct FrameInfo ));
ZeroMemory(&cursor, sizeof(struct CursorInfo));
struct FrameInfo frame = {0};
struct CursorInfo cursor = {0};
frame.buffer = m_frame[m_frameIndex];
frame.bufferSize = m_frameSize;
@ -323,8 +321,6 @@ bool Service::Process()
// update the flags
INTERLOCKED_AND8((volatile char *)flags, KVMFR_HEADER_FLAG_RESTART);
// _mm_sfence();
return true;
}