[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); m_mfTransform->DeleteInputStream(0);
} }
if (m_releaseFrame) ReleaseFrame();
{
m_releaseFrame = false;
m_dup->ReleaseFrame();
}
if (m_pointer) if (m_pointer)
{ {
@ -611,26 +607,6 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
{ {
while (true) 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); status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
if (status == DXGI_ERROR_WAIT_TIMEOUT) if (status == DXGI_ERROR_WAIT_TIMEOUT)
{ {
@ -745,6 +721,7 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
if (!texture) if (!texture)
{ {
ReleaseFrame();
DEBUG_ERROR("Failed to get src ID3D11Texture2D"); DEBUG_ERROR("Failed to get src ID3D11Texture2D");
return GRAB_STATUS_ERROR; return GRAB_STATUS_ERROR;
} }
@ -752,6 +729,30 @@ GrabStatus Capture::DXGI::GrabFrameTexture(struct FrameInfo & frame, struct Curs
return GRAB_STATUS_OK; 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 Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cursor)
{ {
GrabStatus result; GrabStatus result;
@ -762,7 +763,10 @@ GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cu
{ {
result = GrabFrameTexture(frame, cursor, src, timeout); result = GrabFrameTexture(frame, cursor, src, timeout);
if (result != GRAB_STATUS_OK) if (result != GRAB_STATUS_OK)
{
ReleaseFrame();
return result; return result;
}
if (timeout) if (timeout)
{ {
@ -785,6 +789,10 @@ GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cu
m_deviceContext->CopyResource(m_texture, src); m_deviceContext->CopyResource(m_texture, src);
SafeRelease(&src); SafeRelease(&src);
result = ReleaseFrame();
if (result != GRAB_STATUS_OK)
return result;
if (m_surfaceMapped) if (m_surfaceMapped)
{ {
m_deviceContext->Unmap(m_texture, 0); 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); result = GrabFrameTexture(frame, cursor, src, timeout);
if (result != GRAB_STATUS_OK) if (result != GRAB_STATUS_OK)
{ {
ReleaseFrame();
return result; return result;
} }
@ -898,6 +907,7 @@ GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorI
SafeRelease(&sample); SafeRelease(&sample);
SafeRelease(&buffer); SafeRelease(&buffer);
ReleaseFrame();
EnterCriticalSection(&m_encodeCS); EnterCriticalSection(&m_encodeCS);
} }

View File

@ -117,6 +117,7 @@ namespace Capture
bool InitH264Capture(); bool InitH264Capture();
GrabStatus GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout); GrabStatus GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout);
GrabStatus ReleaseFrame();
GrabStatus GrabFrameRaw (struct FrameInfo & frame, struct CursorInfo & cursor); GrabStatus GrabFrameRaw (struct FrameInfo & frame, struct CursorInfo & cursor);
GrabStatus GrabFrameH264 (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_cursorDataSize = 0;
m_frameSize = 0; m_frameSize = 0;
WaitForSingleObject(m_cursorThread, INFINITE);
CloseHandle(m_cursorThread);
CloseHandle(m_cursorEvent);
m_ivshmem->DeInitialize(); m_ivshmem->DeInitialize();
if (m_capture) if (m_capture)
@ -165,10 +169,6 @@ void Service::DeInitialize()
m_capture = NULL; m_capture = NULL;
} }
WaitForSingleObject(m_cursorThread, INFINITE);
CloseHandle(m_cursorThread);
CloseHandle(m_cursorEvent );
m_memory = NULL; m_memory = NULL;
m_initialized = false; m_initialized = false;
} }
@ -213,10 +213,8 @@ bool Service::Process()
Sleep(2); Sleep(2);
} }
struct FrameInfo frame; struct FrameInfo frame = {0};
struct CursorInfo cursor; struct CursorInfo cursor = {0};
ZeroMemory(&frame , sizeof(struct FrameInfo ));
ZeroMemory(&cursor, sizeof(struct CursorInfo));
frame.buffer = m_frame[m_frameIndex]; frame.buffer = m_frame[m_frameIndex];
frame.bufferSize = m_frameSize; frame.bufferSize = m_frameSize;
@ -323,8 +321,6 @@ bool Service::Process()
// update the flags // update the flags
INTERLOCKED_AND8((volatile char *)flags, KVMFR_HEADER_FLAG_RESTART); INTERLOCKED_AND8((volatile char *)flags, KVMFR_HEADER_FLAG_RESTART);
// _mm_sfence();
return true; return true;
} }