mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 16:51:31 +00:00
[idd] transport: abstract LGMP implementation
Introduce transport, frame, and control interfaces with an LGMP factory backend. Move LGMP and IVSHMEM implementation details under transport/lgmp and expose direct frame-buffer memory through a neutral capability.
This commit is contained in:
@@ -36,7 +36,7 @@
|
|||||||
#include "display/IddCxCompat.h"
|
#include "display/IddCxCompat.h"
|
||||||
#include "display/device/CDeviceContext.h"
|
#include "display/device/CDeviceContext.h"
|
||||||
#include "display/monitor/Context.h"
|
#include "display/monitor/Context.h"
|
||||||
#include "transport/CLGMPControl.h"
|
#include "transport/IControlTransport.h"
|
||||||
#include "transport/CPipeServer.h"
|
#include "transport/CPipeServer.h"
|
||||||
#include "config/CSettings.h"
|
#include "config/CSettings.h"
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ NTSTATUS LGIddMonitorSetGammaRamp(IDDCX_MONITOR monitor, const IDARG_IN_SET_GAMM
|
|||||||
{
|
{
|
||||||
auto * wrapper = WdfObjectGet_CMonitorContextWrapper(monitor);
|
auto * wrapper = WdfObjectGet_CMonitorContextWrapper(monitor);
|
||||||
auto * ctx = wrapper->context->GetDeviceContext();
|
auto * ctx = wrapper->context->GetDeviceContext();
|
||||||
auto & control = ctx->GetLGMPControl();
|
auto & control = ctx->GetTransport().Control();
|
||||||
|
|
||||||
if (ctx->IsSoftwareMode())
|
if (ctx->IsSoftwareMode())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
<ClCompile Include="capture\CFrameBufferResource.cpp" />
|
<ClCompile Include="capture\CFrameBufferResource.cpp" />
|
||||||
<ClCompile Include="capture\CFrameProcessor.cpp" />
|
<ClCompile Include="capture\CFrameProcessor.cpp" />
|
||||||
<ClCompile Include="capture\CFrameProcessorUtil.cpp" />
|
<ClCompile Include="capture\CFrameProcessorUtil.cpp" />
|
||||||
<ClCompile Include="capture\CFrameScheduler.cpp" />
|
|
||||||
<ClCompile Include="capture\CHardwareFrameProcessor.cpp" />
|
<ClCompile Include="capture\CHardwareFrameProcessor.cpp" />
|
||||||
<ClCompile Include="capture\CSoftwareFrameProcessor.cpp" />
|
<ClCompile Include="capture\CSoftwareFrameProcessor.cpp" />
|
||||||
<ClCompile Include="capture\CSwapChainCursor.cpp" />
|
<ClCompile Include="capture\CSwapChainCursor.cpp" />
|
||||||
@@ -53,11 +52,14 @@
|
|||||||
<ClCompile Include="postprocess\effect\CDownsampleEffect.cpp" />
|
<ClCompile Include="postprocess\effect\CDownsampleEffect.cpp" />
|
||||||
<ClCompile Include="postprocess\effect\CHDR16to10Effect.cpp" />
|
<ClCompile Include="postprocess\effect\CHDR16to10Effect.cpp" />
|
||||||
<ClCompile Include="postprocess\effect\CRGB24Effect.cpp" />
|
<ClCompile Include="postprocess\effect\CRGB24Effect.cpp" />
|
||||||
<ClCompile Include="transport\CFrameTransport.cpp" />
|
<ClCompile Include="transport\CFrameScheduler.cpp" />
|
||||||
<ClCompile Include="transport\CIVSHMEM.cpp" />
|
|
||||||
<ClCompile Include="transport\CLGMPControl.cpp" />
|
|
||||||
<ClCompile Include="transport\CLGMPHost.cpp" />
|
|
||||||
<ClCompile Include="transport\CPipeServer.cpp" />
|
<ClCompile Include="transport\CPipeServer.cpp" />
|
||||||
|
<ClCompile Include="transport\TransportFactory.cpp" />
|
||||||
|
<ClCompile Include="transport\lgmp\CIVSHMEM.cpp" />
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPControl.cpp" />
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPFrameTransport.cpp" />
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPHost.cpp" />
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPTransport.cpp" />
|
||||||
<ClCompile Include="config\CSettings.cpp" />
|
<ClCompile Include="config\CSettings.cpp" />
|
||||||
<ClCompile Include="platform\CPlatformInfo.cpp" />
|
<ClCompile Include="platform\CPlatformInfo.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -75,10 +77,8 @@
|
|||||||
<ClInclude Include="display\monitor\Context.h" />
|
<ClInclude Include="display\monitor\Context.h" />
|
||||||
<ClInclude Include="capture\CFrameBufferPool.h" />
|
<ClInclude Include="capture\CFrameBufferPool.h" />
|
||||||
<ClInclude Include="capture\CFrameBufferResource.h" />
|
<ClInclude Include="capture\CFrameBufferResource.h" />
|
||||||
<ClInclude Include="capture\FrameBufferTypes.h" />
|
|
||||||
<ClInclude Include="capture\CFrameProcessor.h" />
|
<ClInclude Include="capture\CFrameProcessor.h" />
|
||||||
<ClInclude Include="capture\CFrameProcessorUtil.h" />
|
<ClInclude Include="capture\CFrameProcessorUtil.h" />
|
||||||
<ClInclude Include="capture\CFrameScheduler.h" />
|
|
||||||
<ClInclude Include="capture\CHardwareFrameProcessor.h" />
|
<ClInclude Include="capture\CHardwareFrameProcessor.h" />
|
||||||
<ClInclude Include="capture\CSoftwareFrameProcessor.h" />
|
<ClInclude Include="capture\CSoftwareFrameProcessor.h" />
|
||||||
<ClInclude Include="capture\CSwapChainProcessor.h" />
|
<ClInclude Include="capture\CSwapChainProcessor.h" />
|
||||||
@@ -94,12 +94,20 @@
|
|||||||
<ClInclude Include="postprocess\effect\CDownsampleEffect.h" />
|
<ClInclude Include="postprocess\effect\CDownsampleEffect.h" />
|
||||||
<ClInclude Include="postprocess\effect\CHDR16to10Effect.h" />
|
<ClInclude Include="postprocess\effect\CHDR16to10Effect.h" />
|
||||||
<ClInclude Include="postprocess\effect\CRGB24Effect.h" />
|
<ClInclude Include="postprocess\effect\CRGB24Effect.h" />
|
||||||
<ClInclude Include="transport\CFrameTransport.h" />
|
<ClInclude Include="transport\CFrameScheduler.h" />
|
||||||
<ClInclude Include="transport\CIVSHMEM.h" />
|
|
||||||
<ClInclude Include="transport\CLGMPControl.h" />
|
|
||||||
<ClInclude Include="transport\CLGMPHost.h" />
|
|
||||||
<ClInclude Include="transport\CPipeServer.h" />
|
<ClInclude Include="transport\CPipeServer.h" />
|
||||||
|
<ClInclude Include="transport\FrameBufferTypes.h" />
|
||||||
<ClInclude Include="transport\FrameMemoryLimits.h" />
|
<ClInclude Include="transport\FrameMemoryLimits.h" />
|
||||||
|
<ClInclude Include="transport\IControlTransport.h" />
|
||||||
|
<ClInclude Include="transport\IFrameTransport.h" />
|
||||||
|
<ClInclude Include="transport\ITransport.h" />
|
||||||
|
<ClInclude Include="transport\TransportFactory.h" />
|
||||||
|
<ClInclude Include="transport\TransportTypes.h" />
|
||||||
|
<ClInclude Include="transport\lgmp\CIVSHMEM.h" />
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPControl.h" />
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPFrameTransport.h" />
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPHost.h" />
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPTransport.h" />
|
||||||
<ClInclude Include="config\CSettings.h" />
|
<ClInclude Include="config\CSettings.h" />
|
||||||
<ClInclude Include="platform\CPlatformInfo.h" />
|
<ClInclude Include="platform\CPlatformInfo.h" />
|
||||||
<ClInclude Include="util\CSRWLock.h" />
|
<ClInclude Include="util\CSRWLock.h" />
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
<Filter Include="Transport">
|
<Filter Include="Transport">
|
||||||
<UniqueIdentifier>{22FDF1F6-0A8C-4B96-9E74-53D74733CC0A}</UniqueIdentifier>
|
<UniqueIdentifier>{22FDF1F6-0A8C-4B96-9E74-53D74733CC0A}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Transport\LGMP">
|
||||||
|
<UniqueIdentifier>{530EE339-4AD6-4AE7-9A74-09420E73D04B}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
<Filter Include="Configuration">
|
<Filter Include="Configuration">
|
||||||
<UniqueIdentifier>{82810F1C-E51C-4DBD-86B2-1CDE8C16A2A9}</UniqueIdentifier>
|
<UniqueIdentifier>{82810F1C-E51C-4DBD-86B2-1CDE8C16A2A9}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
@@ -91,18 +94,12 @@
|
|||||||
<ClInclude Include="capture\CFrameBufferResource.h">
|
<ClInclude Include="capture\CFrameBufferResource.h">
|
||||||
<Filter>Capture</Filter>
|
<Filter>Capture</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="capture\FrameBufferTypes.h">
|
|
||||||
<Filter>Capture</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="capture\CFrameProcessor.h">
|
<ClInclude Include="capture\CFrameProcessor.h">
|
||||||
<Filter>Capture</Filter>
|
<Filter>Capture</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="capture\CFrameProcessorUtil.h">
|
<ClInclude Include="capture\CFrameProcessorUtil.h">
|
||||||
<Filter>Capture</Filter>
|
<Filter>Capture</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="capture\CFrameScheduler.h">
|
|
||||||
<Filter>Capture</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="capture\CHardwareFrameProcessor.h">
|
<ClInclude Include="capture\CHardwareFrameProcessor.h">
|
||||||
<Filter>Capture</Filter>
|
<Filter>Capture</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -148,24 +145,48 @@
|
|||||||
<ClInclude Include="postprocess\effect\CRGB24Effect.h">
|
<ClInclude Include="postprocess\effect\CRGB24Effect.h">
|
||||||
<Filter>Post-processing\Effects</Filter>
|
<Filter>Post-processing\Effects</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="transport\CFrameTransport.h">
|
<ClInclude Include="transport\CFrameScheduler.h">
|
||||||
<Filter>Transport</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="transport\CIVSHMEM.h">
|
|
||||||
<Filter>Transport</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="transport\CLGMPControl.h">
|
|
||||||
<Filter>Transport</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="transport\CLGMPHost.h">
|
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="transport\CPipeServer.h">
|
<ClInclude Include="transport\CPipeServer.h">
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\FrameBufferTypes.h">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="transport\FrameMemoryLimits.h">
|
<ClInclude Include="transport\FrameMemoryLimits.h">
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\IControlTransport.h">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\IFrameTransport.h">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\ITransport.h">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\TransportFactory.h">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\TransportTypes.h">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\lgmp\CIVSHMEM.h">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPControl.h">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPFrameTransport.h">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPHost.h">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\lgmp\CLGMPTransport.h">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="config\CSettings.h">
|
<ClInclude Include="config\CSettings.h">
|
||||||
<Filter>Configuration</Filter>
|
<Filter>Configuration</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -213,9 +234,6 @@
|
|||||||
<ClCompile Include="capture\CFrameProcessorUtil.cpp">
|
<ClCompile Include="capture\CFrameProcessorUtil.cpp">
|
||||||
<Filter>Capture</Filter>
|
<Filter>Capture</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="capture\CFrameScheduler.cpp">
|
|
||||||
<Filter>Capture</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="capture\CHardwareFrameProcessor.cpp">
|
<ClCompile Include="capture\CHardwareFrameProcessor.cpp">
|
||||||
<Filter>Capture</Filter>
|
<Filter>Capture</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -264,21 +282,30 @@
|
|||||||
<ClCompile Include="postprocess\effect\CRGB24Effect.cpp">
|
<ClCompile Include="postprocess\effect\CRGB24Effect.cpp">
|
||||||
<Filter>Post-processing\Effects</Filter>
|
<Filter>Post-processing\Effects</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="transport\CFrameTransport.cpp">
|
<ClCompile Include="transport\CFrameScheduler.cpp">
|
||||||
<Filter>Transport</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="transport\CIVSHMEM.cpp">
|
|
||||||
<Filter>Transport</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="transport\CLGMPControl.cpp">
|
|
||||||
<Filter>Transport</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="transport\CLGMPHost.cpp">
|
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="transport\CPipeServer.cpp">
|
<ClCompile Include="transport\CPipeServer.cpp">
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="transport\TransportFactory.cpp">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="transport\lgmp\CIVSHMEM.cpp">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPControl.cpp">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPFrameTransport.cpp">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPHost.cpp">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="transport\lgmp\CLGMPTransport.cpp">
|
||||||
|
<Filter>Transport\LGMP</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="config\CSettings.cpp">
|
<ClCompile Include="config\CSettings.cpp">
|
||||||
<Filter>Configuration</Filter>
|
<Filter>Configuration</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -19,11 +19,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "capture/CFrameBufferPool.h"
|
#include "capture/CFrameBufferPool.h"
|
||||||
|
#include "transport/IFrameTransport.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void CFrameBufferPool::Init(
|
void CFrameBufferPool::Init(
|
||||||
CFrameTransport * transport, CD3D12Device * dx12)
|
IFrameTransport * transport, CD3D12Device * dx12)
|
||||||
{
|
{
|
||||||
m_transport = transport;
|
m_transport = transport;
|
||||||
m_dx12 = dx12;
|
m_dx12 = dx12;
|
||||||
@@ -43,8 +44,9 @@ CFrameBufferResource * CFrameBufferPool::Get(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
CFrameBufferResource * fbr = &m_buffers[buffer.frameIndex];
|
CFrameBufferResource * fbr = &m_buffers[buffer.frameIndex];
|
||||||
if (!fbr->Init(m_transport, m_dx12, buffer.frameIndex, buffer.mem,
|
if (!fbr->Init(m_dx12, buffer.frameIndex, buffer.mem,
|
||||||
minSize, textureDesc))
|
buffer.heapOffset, minSize, m_transport->GetMaxFrameSize(),
|
||||||
|
textureDesc))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return fbr;
|
return fbr;
|
||||||
|
|||||||
@@ -21,22 +21,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "capture/CFrameBufferResource.h"
|
#include "capture/CFrameBufferResource.h"
|
||||||
#include "capture/FrameBufferTypes.h"
|
#include "transport/FrameBufferTypes.h"
|
||||||
#include "common/KVMFR.h"
|
#include "transport/TransportTypes.h"
|
||||||
|
|
||||||
struct CD3D12Device;
|
struct CD3D12Device;
|
||||||
class CFrameTransport;
|
class IFrameTransport;
|
||||||
|
|
||||||
class CFrameBufferPool
|
class CFrameBufferPool
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
CFrameTransport * m_transport = nullptr;
|
IFrameTransport * m_transport = nullptr;
|
||||||
CD3D12Device * m_dx12 = nullptr;
|
CD3D12Device * m_dx12 = nullptr;
|
||||||
|
|
||||||
CFrameBufferResource m_buffers[LGMP_Q_FRAME_BUFFER_LEN];
|
CFrameBufferResource m_buffers[TRANSPORT_FRAME_BUFFER_COUNT];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(CFrameTransport * transport, CD3D12Device * dx12);
|
void Init(IFrameTransport * transport, CD3D12Device * dx12);
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
CFrameBufferResource * Get(const PreparedFrameBuffer& buffer,
|
CFrameBufferResource * Get(const PreparedFrameBuffer& buffer,
|
||||||
|
|||||||
@@ -21,21 +21,19 @@
|
|||||||
#include "capture/CFrameBufferResource.h"
|
#include "capture/CFrameBufferResource.h"
|
||||||
#include "capture/CFrameProcessorUtil.h"
|
#include "capture/CFrameProcessorUtil.h"
|
||||||
#include "d3d/CD3D12Device.h"
|
#include "d3d/CD3D12Device.h"
|
||||||
#include "transport/CFrameTransport.h"
|
|
||||||
#include "transport/CIVSHMEM.h"
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
bool CFrameBufferResource::Init(CFrameTransport * transport,
|
bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
||||||
CD3D12Device * dx12, unsigned frameIndex, uint8_t * base, size_t size,
|
unsigned frameIndex, uint8_t * base, uint64_t heapOffset, size_t size,
|
||||||
const D3D12_RESOURCE_DESC * textureDesc)
|
size_t maxFrameSize, const D3D12_RESOURCE_DESC * textureDesc)
|
||||||
{
|
{
|
||||||
m_frameIndex = frameIndex;
|
m_frameIndex = frameIndex;
|
||||||
|
|
||||||
if (size > transport->GetMaxFrameSize())
|
if (size > maxFrameSize)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Frame size of %llu is too large to fit in shared ram",
|
DEBUG_ERROR("Frame size of %llu is too large for transport memory",
|
||||||
(unsigned long long)size);
|
(unsigned long long)size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -47,7 +45,7 @@ bool CFrameBufferResource::Init(CFrameTransport * transport,
|
|||||||
D3D12_RESOURCE_DESC desc = {};
|
D3D12_RESOURCE_DESC desc = {};
|
||||||
if (textureDesc)
|
if (textureDesc)
|
||||||
{
|
{
|
||||||
if (indirect || !dx12->CanUseIVSHMEMTexture())
|
if (indirect || !dx12->CanUseDirectTexture())
|
||||||
return false;
|
return false;
|
||||||
desc = *textureDesc;
|
desc = *textureDesc;
|
||||||
if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
|
if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
|
||||||
@@ -130,20 +128,19 @@ bool CFrameBufferResource::Init(CFrameTransport * transport,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const UINT64 heapOffset =
|
|
||||||
(uintptr_t)base -
|
|
||||||
(uintptr_t)transport->GetIVSHMEM().GetMem();
|
|
||||||
const D3D12_RESOURCE_ALLOCATION_INFO allocation =
|
const D3D12_RESOURCE_ALLOCATION_INFO allocation =
|
||||||
dx12->GetDevice()->GetResourceAllocationInfo(0, 1, &desc);
|
dx12->GetDevice()->GetResourceAllocationInfo(0, 1, &desc);
|
||||||
allocationSize = allocation.SizeInBytes;
|
allocationSize = allocation.SizeInBytes;
|
||||||
const D3D12_HEAP_DESC heapDesc = dx12->GetHeap()->GetDesc();
|
const D3D12_HEAP_DESC heapDesc =
|
||||||
|
dx12->GetTransportHeap()->GetDesc();
|
||||||
if (!allocation.Alignment ||
|
if (!allocation.Alignment ||
|
||||||
heapOffset % allocation.Alignment ||
|
heapOffset % allocation.Alignment ||
|
||||||
allocation.SizeInBytes > transport->GetMaxFrameSize() ||
|
allocation.SizeInBytes > maxFrameSize ||
|
||||||
heapOffset > heapDesc.SizeInBytes ||
|
heapOffset > heapDesc.SizeInBytes ||
|
||||||
allocation.SizeInBytes > heapDesc.SizeInBytes - heapOffset)
|
allocation.SizeInBytes > heapDesc.SizeInBytes - heapOffset)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("IVSHMEM resource does not fit its framebuffer allocation");
|
DEBUG_ERROR(
|
||||||
|
"Transport resource does not fit its framebuffer allocation");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,20 +153,20 @@ bool CFrameBufferResource::Init(CFrameTransport * transport,
|
|||||||
if (FAILED(hr) ||
|
if (FAILED(hr) ||
|
||||||
!(support.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D))
|
!(support.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("IVSHMEM texture format is unsupported");
|
DEBUG_ERROR("Transport texture format is unsupported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DEBUG_TRACE("Creating IVSHMEM texture for %p", base);
|
DEBUG_TRACE("Creating transport texture for %p", base);
|
||||||
resName = L"IVSHMEM Texture";
|
resName = L"Transport Texture";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_TRACE("Creating IVSHMEM buffer for %p", base);
|
DEBUG_TRACE("Creating transport buffer for %p", base);
|
||||||
resName = L"IVSHMEM";
|
resName = L"Transport Buffer";
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = dx12->GetDevice()->CreatePlacedResource(
|
hr = dx12->GetDevice()->CreatePlacedResource(
|
||||||
dx12->GetHeap().Get(),
|
dx12->GetTransportHeap().Get(),
|
||||||
heapOffset,
|
heapOffset,
|
||||||
&desc,
|
&desc,
|
||||||
D3D12_RESOURCE_STATE_COMMON,
|
D3D12_RESOURCE_STATE_COMMON,
|
||||||
|
|||||||
@@ -27,11 +27,10 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "capture/CFrameScheduler.h"
|
#include "transport/CFrameScheduler.h"
|
||||||
#include "d3d/CInteropResource.h"
|
#include "d3d/CInteropResource.h"
|
||||||
|
|
||||||
struct CD3D12Device;
|
struct CD3D12Device;
|
||||||
class CFrameTransport;
|
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
@@ -70,8 +69,8 @@ class CFrameBufferResource
|
|||||||
void * m_map = nullptr;
|
void * m_map = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Init(CFrameTransport * transport, CD3D12Device * dx12,
|
bool Init(CD3D12Device * dx12, unsigned frameIndex, uint8_t * base,
|
||||||
unsigned frameIndex, uint8_t * base, size_t size,
|
uint64_t heapOffset, size_t size, size_t maxFrameSize,
|
||||||
const D3D12_RESOURCE_DESC * textureDesc = nullptr);
|
const D3D12_RESOURCE_DESC * textureDesc = nullptr);
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,9 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
CFrameProcessor::CFrameProcessor(CFrameTransport * transport,
|
CFrameProcessor::CFrameProcessor(IFrameTransport * transport,
|
||||||
std::shared_ptr<CD3D12Device> dx12,
|
std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
||||||
m_transport(transport),
|
m_transport(transport),
|
||||||
m_dx12(std::move(dx12)),
|
m_dx12(std::move(dx12)),
|
||||||
@@ -154,9 +154,9 @@ void CFrameProcessor::GetPreviousDamage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CFrameProcessor> CreateFrameProcessor(
|
std::unique_ptr<CFrameProcessor> CreateFrameProcessor(
|
||||||
bool software, CFrameTransport * transport,
|
bool software, IFrameTransport * transport,
|
||||||
std::shared_ptr<CD3D12Device> dx12,
|
std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent)
|
SRWLOCK * pipelineLock, HANDLE terminateEvent)
|
||||||
{
|
{
|
||||||
std::unique_ptr<CFrameProcessor> processor;
|
std::unique_ptr<CFrameProcessor> processor;
|
||||||
|
|||||||
@@ -24,13 +24,15 @@
|
|||||||
#include "capture/CFrameBufferPool.h"
|
#include "capture/CFrameBufferPool.h"
|
||||||
#include "d3d/CInteropResource.h"
|
#include "d3d/CInteropResource.h"
|
||||||
#include "postprocess/CPostProcessor.h"
|
#include "postprocess/CPostProcessor.h"
|
||||||
|
#include "transport/CFrameScheduler.h"
|
||||||
|
#include "transport/TransportTypes.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
class CFrameTransport;
|
class IFrameTransport;
|
||||||
|
|
||||||
struct FrameSubmission
|
struct FrameSubmission
|
||||||
{
|
{
|
||||||
@@ -46,7 +48,7 @@ struct FrameSubmission
|
|||||||
class CFrameProcessor
|
class CFrameProcessor
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
CFrameTransport * m_transport;
|
IFrameTransport * m_transport;
|
||||||
std::shared_ptr<CD3D12Device> m_dx12;
|
std::shared_ptr<CD3D12Device> m_dx12;
|
||||||
CPostProcessor * m_postProcessors;
|
CPostProcessor * m_postProcessors;
|
||||||
SRWLOCK * m_pipelineLock;
|
SRWLOCK * m_pipelineLock;
|
||||||
@@ -72,9 +74,9 @@ protected:
|
|||||||
virtual void SetFullDamageLocked();
|
virtual void SetFullDamageLocked();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CFrameProcessor(CFrameTransport * transport,
|
CFrameProcessor(IFrameTransport * transport,
|
||||||
std::shared_ptr<CD3D12Device> dx12,
|
std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
||||||
virtual ~CFrameProcessor() = default;
|
virtual ~CFrameProcessor() = default;
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<CFrameProcessor> CreateFrameProcessor(
|
std::unique_ptr<CFrameProcessor> CreateFrameProcessor(
|
||||||
bool software, CFrameTransport * transport,
|
bool software, IFrameTransport * transport,
|
||||||
std::shared_ptr<CD3D12Device> dx12,
|
std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "capture/CHardwareFrameProcessor.h"
|
#include "capture/CHardwareFrameProcessor.h"
|
||||||
#include "capture/CFrameProcessorUtil.h"
|
#include "capture/CFrameProcessorUtil.h"
|
||||||
#include "transport/CFrameTransport.h"
|
#include "transport/IFrameTransport.h"
|
||||||
#include "util/CSRWLock.h"
|
#include "util/CSRWLock.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
static_assert(LGMP_Q_FRAME_LEN == 2,
|
static_assert(TRANSPORT_FRAME_QUEUE_LENGTH == 2,
|
||||||
"IDD candidate pipeline assumes two slots");
|
"IDD candidate pipeline assumes two slots");
|
||||||
|
|
||||||
class CPublishPending
|
class CPublishPending
|
||||||
@@ -71,8 +71,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CHardwareFrameProcessor::CHardwareFrameProcessor(
|
CHardwareFrameProcessor::CHardwareFrameProcessor(
|
||||||
CFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
|
IFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
||||||
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
||||||
pipelineLock, terminateEvent)
|
pipelineLock, terminateEvent)
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ private:
|
|||||||
bool active = false;
|
bool active = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
FrameCandidate m_candidates[LGMP_Q_FRAME_LEN];
|
FrameCandidate m_candidates[TRANSPORT_FRAME_QUEUE_LENGTH];
|
||||||
CandidateDamageTail m_candidateDamageTail[LGMP_Q_FRAME_LEN];
|
CandidateDamageTail m_candidateDamageTail[TRANSPORT_FRAME_QUEUE_LENGTH];
|
||||||
mutable SRWLOCK m_candidateLock = SRWLOCK_INIT;
|
mutable SRWLOCK m_candidateLock = SRWLOCK_INIT;
|
||||||
SRWLOCK m_copySubmitLock = SRWLOCK_INIT;
|
SRWLOCK m_copySubmitLock = SRWLOCK_INIT;
|
||||||
uint64_t m_candidateSequence = 0;
|
uint64_t m_candidateSequence = 0;
|
||||||
@@ -89,9 +89,9 @@ private:
|
|||||||
void SetFullDamageLocked() override;
|
void SetFullDamageLocked() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CHardwareFrameProcessor(CFrameTransport * transport,
|
CHardwareFrameProcessor(IFrameTransport * transport,
|
||||||
std::shared_ptr<CD3D12Device> dx12,
|
std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
||||||
|
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|||||||
@@ -20,21 +20,21 @@
|
|||||||
|
|
||||||
#include "capture/CSoftwareFrameProcessor.h"
|
#include "capture/CSoftwareFrameProcessor.h"
|
||||||
#include "capture/CFrameProcessorUtil.h"
|
#include "capture/CFrameProcessorUtil.h"
|
||||||
#include "capture/FrameBufferTypes.h"
|
#include "transport/TransportTypes.h"
|
||||||
#include "transport/CFrameTransport.h"
|
#include "transport/IFrameTransport.h"
|
||||||
#include "util/CSRWLock.h"
|
#include "util/CSRWLock.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
CSoftwareFrameProcessor::CSoftwareFrameProcessor(
|
CSoftwareFrameProcessor::CSoftwareFrameProcessor(
|
||||||
CFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
|
IFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
||||||
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
||||||
pipelineLock, terminateEvent),
|
pipelineLock, terminateEvent),
|
||||||
m_directTexture(
|
m_directTexture(
|
||||||
!m_dx12->IsIndirectCopy() && m_dx12->CanUseIVSHMEMTexture())
|
!m_dx12->IsIndirectCopy() && m_dx12->CanUseDirectTexture())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,18 +152,18 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_directTexture = false;
|
m_directTexture = false;
|
||||||
DEBUG_WARN("IVSHMEM texture layout does not fit the framebuffer");
|
DEBUG_WARN("Transport texture layout does not fit the framebuffer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_directTexture)
|
else if (m_directTexture)
|
||||||
{
|
{
|
||||||
m_directTexture = false;
|
m_directTexture = false;
|
||||||
DEBUG_WARN("Post-processor output cannot use an IVSHMEM texture");
|
DEBUG_WARN("Post-processor output cannot use a transport texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pitch || !frameSize || frameSize > m_transport->GetMaxFrameSize())
|
if (!pitch || !frameSize || frameSize > m_transport->GetMaxFrameSize())
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Software frame does not fit in shared memory");
|
DEBUG_ERROR("Software frame does not fit in transport memory");
|
||||||
SetFullDamage();
|
SetFullDamage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
|
|||||||
deliverySchedule.deliveryDeadlineSerial = 0;
|
deliverySchedule.deliveryDeadlineSerial = 0;
|
||||||
deliverySchedule.phaseEligible = false;
|
deliverySchedule.phaseEligible = false;
|
||||||
|
|
||||||
m_transport->ProcessFrameQueue();
|
m_transport->ProcessDeliveries();
|
||||||
if (!m_transport->FrameBufferAvailable(
|
if (!m_transport->FrameBufferAvailable(
|
||||||
deliverySchedule, submission.noImageUpdate))
|
deliverySchedule, submission.noImageUpdate))
|
||||||
{
|
{
|
||||||
@@ -258,7 +258,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
|
|||||||
RestorePendingDamage(
|
RestorePendingDamage(
|
||||||
currentDirtyRects, nbDirtyRects, hasDamage);
|
currentDirtyRects, nbDirtyRects, hasDamage);
|
||||||
DEBUG_ERROR_HR(deviceStatus,
|
DEBUG_ERROR_HR(deviceStatus,
|
||||||
"D3D12 device removed while creating an IVSHMEM texture");
|
"D3D12 device removed while creating a transport texture");
|
||||||
SetFullDamage();
|
SetFullDamage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
|
|||||||
m_directTexture = false;
|
m_directTexture = false;
|
||||||
textureDescPtr = nullptr;
|
textureDescPtr = nullptr;
|
||||||
DEBUG_WARN(
|
DEBUG_WARN(
|
||||||
"IVSHMEM textures unavailable; using a direct buffer copy");
|
"Transport textures unavailable; using a direct buffer copy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ private:
|
|||||||
CD3D12CommandSlot * slot, bool result, void * param1, void * param2);
|
CD3D12CommandSlot * slot, bool result, void * param1, void * param2);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSoftwareFrameProcessor(CFrameTransport * transport,
|
CSoftwareFrameProcessor(IFrameTransport * transport,
|
||||||
std::shared_ptr<CD3D12Device> dx12,
|
std::shared_ptr<CD3D12Device> dx12,
|
||||||
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
|
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
SRWLOCK * pipelineLock, HANDLE terminateEvent);
|
||||||
|
|
||||||
bool Submit(const FrameSubmission& submission) override;
|
bool Submit(const FrameSubmission& submission) override;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "display/IddCxCompat.h"
|
#include "display/IddCxCompat.h"
|
||||||
#include "display/device/CDeviceContext.h"
|
#include "display/device/CDeviceContext.h"
|
||||||
#include "transport/CLGMPControl.h"
|
#include "transport/IControlTransport.h"
|
||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
#include "display/device/CDeviceContext.h"
|
#include "display/device/CDeviceContext.h"
|
||||||
#include "display/monitor/Context.h"
|
#include "display/monitor/Context.h"
|
||||||
#include "platform/CPlatformInfo.h"
|
#include "platform/CPlatformInfo.h"
|
||||||
#include "transport/CFrameTransport.h"
|
#include "transport/IFrameTransport.h"
|
||||||
#include "transport/CLGMPControl.h"
|
#include "transport/IControlTransport.h"
|
||||||
#include "util/CSRWLock.h"
|
#include "util/CSRWLock.h"
|
||||||
|
|
||||||
#include <avrt.h>
|
#include <avrt.h>
|
||||||
@@ -49,8 +49,8 @@ CSwapChainProcessor::CSwapChainProcessor(CMonitorContext * monitorContext,
|
|||||||
m_assignmentGeneration(assignmentGeneration),
|
m_assignmentGeneration(assignmentGeneration),
|
||||||
m_monitor(monitor),
|
m_monitor(monitor),
|
||||||
m_devContext(devContext),
|
m_devContext(devContext),
|
||||||
m_transport(devContext->GetFrameTransport()),
|
m_transport(devContext->GetTransport().Frames()),
|
||||||
m_control(devContext->GetLGMPControl()),
|
m_control(devContext->GetTransport().Control()),
|
||||||
m_hSwapChain(hSwapChain),
|
m_hSwapChain(hSwapChain),
|
||||||
m_renderAdapter(renderAdapter),
|
m_renderAdapter(renderAdapter),
|
||||||
m_dx11Device(dx11Device),
|
m_dx11Device(dx11Device),
|
||||||
@@ -99,7 +99,8 @@ bool CSwapChainProcessor::InitializePipeline()
|
|||||||
UINT64 alignSize = CPlatformInfo::GetPageSize();
|
UINT64 alignSize = CPlatformInfo::GetPageSize();
|
||||||
auto dx12Device = std::make_shared<CD3D12Device>(m_renderAdapter);
|
auto dx12Device = std::make_shared<CD3D12Device>(m_renderAdapter);
|
||||||
const CD3D12Device::InitResult result = dx12Device->Init(
|
const CD3D12Device::InitResult result = dx12Device->Init(
|
||||||
m_transport.GetIVSHMEM(), alignSize, !m_dx11Device->IsSoftware());
|
m_devContext->GetTransport().GetDirectMemory(), alignSize,
|
||||||
|
!m_dx11Device->IsSoftware());
|
||||||
if (result == CD3D12Device::RETRY)
|
if (result == CD3D12Device::RETRY)
|
||||||
{
|
{
|
||||||
const HRESULT deviceStatus =
|
const HRESULT deviceStatus =
|
||||||
@@ -115,9 +116,9 @@ bool CSwapChainProcessor::InitializePipeline()
|
|||||||
if (result == CD3D12Device::FAILURE)
|
if (result == CD3D12Device::FAILURE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_devContext->SetupLGMP(alignSize))
|
if (!m_devContext->SetupTransport(alignSize))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("SetupLGMP failed");
|
DEBUG_ERROR("Transport setup failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +334,7 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
// Only the buffer2 acquisition path (IddCx 1.10+) reports it; on the legacy
|
// Only the buffer2 acquisition path (IddCx 1.10+) reports it; on the legacy
|
||||||
// path HDR is not available, so default to SDR.
|
// path HDR is not available, so default to SDR.
|
||||||
DXGI_COLOR_SPACE_TYPE colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
DXGI_COLOR_SPACE_TYPE colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||||
UINT sdrWhiteLevel = KVMFR_SDR_WHITE_LEVEL_DEFAULT;
|
UINT sdrWhiteLevel = LG_SDR_WHITE_LEVEL_DEFAULT;
|
||||||
const uint64_t captureStart = CFrameScheduler::Nanotime();
|
const uint64_t captureStart = CFrameScheduler::Nanotime();
|
||||||
|
|
||||||
#ifdef HAS_IDDCX_110
|
#ifdef HAS_IDDCX_110
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include "display/IddCxCompat.h"
|
#include "display/IddCxCompat.h"
|
||||||
#include "d3d/CInteropResourcePool.h"
|
#include "d3d/CInteropResourcePool.h"
|
||||||
#include "capture/CFrameProcessor.h"
|
#include "capture/CFrameProcessor.h"
|
||||||
#include "common/KVMFR.h"
|
#include "postprocess/D12FrameFormat.h"
|
||||||
#include "postprocess/CPostProcessor.h"
|
#include "postprocess/CPostProcessor.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@@ -37,8 +37,8 @@ using namespace Microsoft::WRL;
|
|||||||
|
|
||||||
class CMonitorContext;
|
class CMonitorContext;
|
||||||
class CDeviceContext;
|
class CDeviceContext;
|
||||||
class CFrameTransport;
|
class IFrameTransport;
|
||||||
class CLGMPControl;
|
class IControlTransport;
|
||||||
|
|
||||||
class CSwapChainProcessor
|
class CSwapChainProcessor
|
||||||
{
|
{
|
||||||
@@ -47,8 +47,8 @@ private:
|
|||||||
UINT64 m_assignmentGeneration;
|
UINT64 m_assignmentGeneration;
|
||||||
IDDCX_MONITOR m_monitor;
|
IDDCX_MONITOR m_monitor;
|
||||||
CDeviceContext * m_devContext;
|
CDeviceContext * m_devContext;
|
||||||
CFrameTransport & m_transport;
|
IFrameTransport & m_transport;
|
||||||
CLGMPControl & m_control;
|
IControlTransport & m_control;
|
||||||
IDDCX_SWAPCHAIN m_hSwapChain;
|
IDDCX_SWAPCHAIN m_hSwapChain;
|
||||||
LUID m_renderAdapter;
|
LUID m_renderAdapter;
|
||||||
std::shared_ptr<CD3D11Device> m_dx11Device;
|
std::shared_ptr<CD3D11Device> m_dx11Device;
|
||||||
@@ -56,7 +56,7 @@ private:
|
|||||||
HANDLE m_newFrameEvent;
|
HANDLE m_newFrameEvent;
|
||||||
|
|
||||||
CInteropResourcePool m_resPool;
|
CInteropResourcePool m_resPool;
|
||||||
CPostProcessor m_postProcessors[LGMP_Q_FRAME_LEN];
|
CPostProcessor m_postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH];
|
||||||
std::unique_ptr<CFrameProcessor> m_frameProcessor;
|
std::unique_ptr<CFrameProcessor> m_frameProcessor;
|
||||||
// Reconfiguration is exclusive while per-candidate recording is shared.
|
// Reconfiguration is exclusive while per-candidate recording is shared.
|
||||||
SRWLOCK m_pipelineLock = SRWLOCK_INIT;
|
SRWLOCK m_pipelineLock = SRWLOCK_INIT;
|
||||||
@@ -68,7 +68,7 @@ private:
|
|||||||
Wrappers::Event m_cursorDataEvent;
|
Wrappers::Event m_cursorDataEvent;
|
||||||
BYTE* m_shapeBuffer;
|
BYTE* m_shapeBuffer;
|
||||||
DWORD m_lastShapeId = 0;
|
DWORD m_lastShapeId = 0;
|
||||||
std::atomic<UINT> m_sdrWhiteLevel { KVMFR_SDR_WHITE_LEVEL_DEFAULT };
|
std::atomic<UINT> m_sdrWhiteLevel { LG_SDR_WHITE_LEVEL_DEFAULT };
|
||||||
|
|
||||||
#ifdef HAS_IDDCX_110
|
#ifdef HAS_IDDCX_110
|
||||||
// The per-frame metadata stream can select the monitor default, provide a
|
// The per-frame metadata stream can select the monitor default, provide a
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "capture/CSwapChainProcessor.h"
|
#include "capture/CSwapChainProcessor.h"
|
||||||
|
|
||||||
#include "transport/CFrameTransport.h"
|
#include "transport/IFrameTransport.h"
|
||||||
|
|
||||||
#include <avrt.h>
|
#include <avrt.h>
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
@@ -83,7 +83,7 @@ void CSwapChainProcessor::PublisherThread()
|
|||||||
const bool ready = m_frameProcessor->HasReadyFrame();
|
const bool ready = m_frameProcessor->HasReadyFrame();
|
||||||
if (!ready)
|
if (!ready)
|
||||||
{
|
{
|
||||||
m_transport.ProcessFrameQueue();
|
m_transport.ProcessDeliveries();
|
||||||
if (m_frameProcessor->HasReadyFrame())
|
if (m_frameProcessor->HasReadyFrame())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -123,12 +123,12 @@ void CSwapChainProcessor::PublisherThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t replayTarget;
|
uint64_t replayTarget;
|
||||||
if (m_transport.GetSharedFrameTarget(current, replayTarget))
|
if (m_transport.GetPendingDeliveryTarget(current, replayTarget))
|
||||||
{
|
{
|
||||||
bool retry = false;
|
bool retry = false;
|
||||||
if (replayTarget <= current)
|
if (replayTarget <= current)
|
||||||
{
|
{
|
||||||
if (m_transport.ReplaySharedFrame(current, retry))
|
if (m_transport.RetryPendingDelivery(current, retry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
current = CFrameScheduler::Nanotime();
|
current = CFrameScheduler::Nanotime();
|
||||||
@@ -205,15 +205,15 @@ void CSwapChainProcessor::PublisherThread()
|
|||||||
|
|
||||||
uint64_t current = CFrameScheduler::Nanotime();
|
uint64_t current = CFrameScheduler::Nanotime();
|
||||||
uint64_t replayTarget;
|
uint64_t replayTarget;
|
||||||
if (m_transport.GetSharedFrameTarget(current, replayTarget) &&
|
if (m_transport.GetPendingDeliveryTarget(current, replayTarget) &&
|
||||||
replayTarget < target)
|
replayTarget < target)
|
||||||
{
|
{
|
||||||
if (replayTarget <= current)
|
if (replayTarget <= current)
|
||||||
{
|
{
|
||||||
m_transport.ProcessFrameQueue();
|
m_transport.ProcessDeliveries();
|
||||||
current = CFrameScheduler::Nanotime();
|
current = CFrameScheduler::Nanotime();
|
||||||
bool retry = false;
|
bool retry = false;
|
||||||
if (m_transport.ReplaySharedFrame(current, retry))
|
if (m_transport.RetryPendingDelivery(current, retry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
current = CFrameScheduler::Nanotime();
|
current = CFrameScheduler::Nanotime();
|
||||||
@@ -251,7 +251,7 @@ void CSwapChainProcessor::PublisherThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t publishStart = CFrameScheduler::Nanotime();
|
const uint64_t publishStart = CFrameScheduler::Nanotime();
|
||||||
m_transport.ProcessFrameQueue();
|
m_transport.ProcessDeliveries();
|
||||||
if (!m_transport.FrameBufferAvailable(schedule) ||
|
if (!m_transport.FrameBufferAvailable(schedule) ||
|
||||||
!m_frameProcessor->Publish(schedule, periodic, publishStart))
|
!m_frameProcessor->Publish(schedule, periodic, publishStart))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "d3d/CD3D12Device.h"
|
#include "d3d/CD3D12Device.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
bool CD3D12Device::m_indirectCopy = false;
|
bool CD3D12Device::s_directHeapFailed = false;
|
||||||
|
|
||||||
CD3D12Device::CD3D12Device(LUID adapterLuid) :
|
CD3D12Device::CD3D12Device(LUID adapterLuid) :
|
||||||
m_adapterLuid(adapterLuid),
|
m_adapterLuid(adapterLuid),
|
||||||
@@ -60,12 +60,14 @@ static void CALLBACK _D3D12DebugCallback(
|
|||||||
description);
|
description);
|
||||||
}
|
}
|
||||||
|
|
||||||
CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem,
|
CD3D12Device::InitResult CD3D12Device::Init(
|
||||||
UINT64 &alignSize, bool enableCompute)
|
const DirectFrameBufferMemory& directMemory,
|
||||||
|
UINT64& alignSize, bool enableCompute)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
m_computeEnabled = enableCompute;
|
m_computeEnabled = enableCompute;
|
||||||
|
m_indirectCopy = !directMemory || s_directHeapFailed;
|
||||||
|
|
||||||
hr = CreateDXGIFactory2(m_debug ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&m_factory));
|
hr = CreateDXGIFactory2(m_debug ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&m_factory));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@@ -105,34 +107,37 @@ CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem,
|
|||||||
|
|
||||||
if (!m_indirectCopy)
|
if (!m_indirectCopy)
|
||||||
{
|
{
|
||||||
hr = m_device->OpenExistingHeapFromAddress(ivshmem.GetMem(), IID_PPV_ARGS(&m_ivshmemHeap));
|
hr = m_device->OpenExistingHeapFromAddress(
|
||||||
|
directMemory.address, IID_PPV_ARGS(&m_transportHeap));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR_HR(hr, "Failed to open IVSHMEM as a D3D12Heap");
|
DEBUG_ERROR_HR(hr,
|
||||||
m_indirectCopy = true;
|
"Failed to open transport memory as a D3D12 heap");
|
||||||
|
s_directHeapFailed = true;
|
||||||
return InitResult::RETRY;
|
return InitResult::RETRY;
|
||||||
}
|
}
|
||||||
m_ivshmemHeap->SetName(L"IVSHMEM");
|
m_transportHeap->SetName(L"Transport Memory");
|
||||||
|
|
||||||
D3D12_HEAP_DESC heapDesc = m_ivshmemHeap->GetDesc();
|
D3D12_HEAP_DESC heapDesc = m_transportHeap->GetDesc();
|
||||||
alignSize = heapDesc.Alignment;
|
alignSize = heapDesc.Alignment;
|
||||||
m_ivshmemTextureSupported =
|
m_directTextureSupported =
|
||||||
(heapDesc.Flags & D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER) &&
|
(heapDesc.Flags & D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER) &&
|
||||||
!(heapDesc.Flags & D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES);
|
!(heapDesc.Flags & D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES);
|
||||||
|
|
||||||
// test that the heap is usable
|
// test that the heap is usable
|
||||||
if (!HeapTest())
|
if (!HeapTest())
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Unable to create resources in the IVSHMEM heap, falling back to indirect copy");
|
DEBUG_WARN("Unable to create resources in transport memory, "
|
||||||
|
"falling back to indirect copy");
|
||||||
|
|
||||||
// failure often results in the device being removed and we need to completely reinit when this occurs
|
// failure often results in the device being removed and we need to completely reinit when this occurs
|
||||||
m_indirectCopy = true;
|
s_directHeapFailed = true;
|
||||||
return InitResult::RETRY;
|
return InitResult::RETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_INFO("Using IVSHMEM as a D3D12Heap");
|
DEBUG_INFO("Using transport memory as a D3D12 heap");
|
||||||
if (!m_ivshmemTextureSupported)
|
if (!m_directTextureSupported)
|
||||||
DEBUG_WARN("IVSHMEM heap does not support placed textures");
|
DEBUG_WARN("Transport memory does not support placed textures");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_copyQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COPY,
|
if (!m_copyQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COPY,
|
||||||
@@ -182,7 +187,7 @@ bool CD3D12Device::HeapTest()
|
|||||||
|
|
||||||
ComPtr<ID3D12Resource> resource;
|
ComPtr<ID3D12Resource> resource;
|
||||||
hr = m_device->CreatePlacedResource(
|
hr = m_device->CreatePlacedResource(
|
||||||
m_ivshmemHeap.Get(),
|
m_transportHeap.Get(),
|
||||||
0,
|
0,
|
||||||
&desc,
|
&desc,
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
@@ -190,7 +195,8 @@ bool CD3D12Device::HeapTest()
|
|||||||
IID_PPV_ARGS(&resource));
|
IID_PPV_ARGS(&resource));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR_HR(hr, "Failed to create the ivshmem ID3D12Resource");
|
DEBUG_ERROR_HR(hr,
|
||||||
|
"Failed to create the transport-memory ID3D12Resource");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
resource->SetName(L"HeapTest");
|
resource->SetName(L"HeapTest");
|
||||||
|
|||||||
@@ -26,8 +26,8 @@
|
|||||||
#include <dxgi1_5.h>
|
#include <dxgi1_5.h>
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
|
|
||||||
#include "transport/CIVSHMEM.h"
|
|
||||||
#include "d3d/CD3D12CommandQueue.h"
|
#include "d3d/CD3D12CommandQueue.h"
|
||||||
|
#include "transport/TransportTypes.h"
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
@@ -37,8 +37,9 @@ struct CD3D12Device
|
|||||||
LUID m_adapterLuid;
|
LUID m_adapterLuid;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
|
|
||||||
// static as this needs to persist if set
|
// A failed direct heap can remove the device. Preserve the fallback for
|
||||||
static bool m_indirectCopy;
|
// the replacement device so initialization does not retry forever.
|
||||||
|
static bool s_directHeapFailed;
|
||||||
|
|
||||||
ComPtr<ID3D12Debug6 > m_dxDebug;
|
ComPtr<ID3D12Debug6 > m_dxDebug;
|
||||||
ComPtr<ID3D12InfoQueue1> m_infoQueue;
|
ComPtr<ID3D12InfoQueue1> m_infoQueue;
|
||||||
@@ -47,12 +48,13 @@ struct CD3D12Device
|
|||||||
ComPtr<IDXGIFactory5> m_factory;
|
ComPtr<IDXGIFactory5> m_factory;
|
||||||
ComPtr<IDXGIAdapter1> m_adapter;
|
ComPtr<IDXGIAdapter1> m_adapter;
|
||||||
ComPtr<ID3D12Device3> m_device;
|
ComPtr<ID3D12Device3> m_device;
|
||||||
ComPtr<ID3D12Heap > m_ivshmemHeap;
|
ComPtr<ID3D12Heap > m_transportHeap;
|
||||||
|
|
||||||
CD3D12CommandQueue m_copyQueue;
|
CD3D12CommandQueue m_copyQueue;
|
||||||
CD3D12CommandQueue m_computeQueue;
|
CD3D12CommandQueue m_computeQueue;
|
||||||
bool m_computeEnabled = false;
|
bool m_computeEnabled = false;
|
||||||
bool m_ivshmemTextureSupported = false;
|
bool m_indirectCopy = true;
|
||||||
|
bool m_directTextureSupported = false;
|
||||||
|
|
||||||
bool HeapTest();
|
bool HeapTest();
|
||||||
|
|
||||||
@@ -67,8 +69,8 @@ struct CD3D12Device
|
|||||||
SUCCESS
|
SUCCESS
|
||||||
};
|
};
|
||||||
|
|
||||||
InitResult Init(CIVSHMEM &ivshmem, UINT64 &alignSize,
|
InitResult Init(const DirectFrameBufferMemory& directMemory,
|
||||||
bool enableCompute);
|
UINT64& alignSize, bool enableCompute);
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
// Wait for all command queues to finish in-flight GPU work and run their
|
// Wait for all command queues to finish in-flight GPU work and run their
|
||||||
@@ -77,9 +79,9 @@ struct CD3D12Device
|
|||||||
void WaitForIdle();
|
void WaitForIdle();
|
||||||
|
|
||||||
ComPtr<ID3D12Device3> GetDevice() { return m_device; }
|
ComPtr<ID3D12Device3> GetDevice() { return m_device; }
|
||||||
ComPtr<ID3D12Heap > GetHeap() { return m_ivshmemHeap; }
|
ComPtr<ID3D12Heap > GetTransportHeap() { return m_transportHeap; }
|
||||||
bool IsIndirectCopy() { return m_indirectCopy; }
|
bool IsIndirectCopy() const { return m_indirectCopy; }
|
||||||
bool CanUseIVSHMEMTexture() { return m_ivshmemTextureSupported; }
|
bool CanUseDirectTexture() const { return m_directTextureSupported; }
|
||||||
|
|
||||||
CD3D12CommandSlot * GetCopySlot ();
|
CD3D12CommandSlot * GetCopySlot ();
|
||||||
CD3D12CommandSlot * GetCopySlot (unsigned frameIndex);
|
CD3D12CommandSlot * GetCopySlot (unsigned frameIndex);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include "display/CDisplayConfiguration.h"
|
#include "display/CDisplayConfiguration.h"
|
||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
#include "common/LGMPConfig.h"
|
|
||||||
#include "util/CSRWLock.h"
|
#include "util/CSRWLock.h"
|
||||||
|
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
@@ -59,12 +58,12 @@ bool CDisplayConfiguration::CalculateFrameSize(
|
|||||||
|
|
||||||
bool CDisplayConfiguration::GetResolutionMemoryRequirements(
|
bool CDisplayConfiguration::GetResolutionMemoryRequirements(
|
||||||
uint32_t width, uint32_t height, UINT64 alignment,
|
uint32_t width, uint32_t height, UINT64 alignment,
|
||||||
const FrameMemoryLimits& limits, UINT64& frameSize, UINT64& sharedSize)
|
const FrameMemoryLimits& limits, UINT64& frameSize, UINT64& requiredSize)
|
||||||
{
|
{
|
||||||
frameSize = 0;
|
frameSize = 0;
|
||||||
sharedSize = 0;
|
requiredSize = 0;
|
||||||
|
|
||||||
if (!alignment || !limits.frameMemoryOffset ||
|
if (!alignment || !limits.frameMemoryOffset || !limits.bufferCount ||
|
||||||
!CalculateFrameSize(width, height, frameSize))
|
!CalculateFrameSize(width, height, frameSize))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -76,12 +75,12 @@ bool CDisplayConfiguration::GetResolutionMemoryRequirements(
|
|||||||
if (!AlignUp(limits.frameMemoryOffset, alignment, frameMemoryStart))
|
if (!AlignUp(limits.frameMemoryOffset, alignment, frameMemoryStart))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sharedSize = frameMemoryStart +
|
requiredSize = frameMemoryStart +
|
||||||
frameAllocationSize * LGMP_Q_FRAME_BUFFER_LEN;
|
frameAllocationSize * limits.bufferCount;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CDisplayConfiguration::RecommendedIVSHMEMSizeMiB(
|
uint32_t CDisplayConfiguration::RecommendedMemorySizeMiB(
|
||||||
UINT64 requiredSize)
|
UINT64 requiredSize)
|
||||||
{
|
{
|
||||||
UINT64 sizeMiB = requiredSize / 1048576;
|
UINT64 sizeMiB = requiredSize / 1048576;
|
||||||
@@ -135,10 +134,10 @@ bool CDisplayConfiguration::LoadModes(const FrameMemoryLimits& limits)
|
|||||||
for (const auto& configuredMode : configuredModes)
|
for (const auto& configuredMode : configuredModes)
|
||||||
{
|
{
|
||||||
UINT64 frameSize;
|
UINT64 frameSize;
|
||||||
UINT64 requiredIVSHMEMSize;
|
UINT64 requiredMemorySize;
|
||||||
if (!GetResolutionMemoryRequirements(configuredMode.width,
|
if (!GetResolutionMemoryRequirements(configuredMode.width,
|
||||||
configuredMode.height, alignment, limits, frameSize,
|
configuredMode.height, alignment, limits, frameSize,
|
||||||
requiredIVSHMEMSize))
|
requiredMemorySize))
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Filtering invalid %s mode %ux%u@%.3f",
|
DEBUG_WARN("Filtering invalid %s mode %ux%u@%.3f",
|
||||||
configuredMode.extraMode ? "extra" : "configured",
|
configuredMode.extraMode ? "extra" : "configured",
|
||||||
@@ -147,15 +146,15 @@ bool CDisplayConfiguration::LoadModes(const FrameMemoryLimits& limits)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requiredIVSHMEMSize > limits.sharedSize)
|
if (requiredMemorySize > limits.capacity)
|
||||||
{
|
{
|
||||||
DEBUG_WARN(
|
DEBUG_WARN(
|
||||||
"Filtering %s mode %ux%u@%.3f: requires %llu bytes of IVSHMEM, only %llu bytes are available",
|
"Filtering %s mode %ux%u@%.3f: requires %llu bytes of transport memory, only %llu bytes are available",
|
||||||
configuredMode.extraMode ? "extra" : "configured",
|
configuredMode.extraMode ? "extra" : "configured",
|
||||||
configuredMode.width, configuredMode.height,
|
configuredMode.width, configuredMode.height,
|
||||||
configuredMode.refreshMilliHz / 1000.0,
|
configuredMode.refreshMilliHz / 1000.0,
|
||||||
(unsigned long long)requiredIVSHMEMSize,
|
(unsigned long long)requiredMemorySize,
|
||||||
(unsigned long long)limits.sharedSize);
|
(unsigned long long)limits.capacity);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +169,7 @@ bool CDisplayConfiguration::LoadModes(const FrameMemoryLimits& limits)
|
|||||||
|
|
||||||
if (newModes.empty())
|
if (newModes.empty())
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("No configured display modes fit in IVSHMEM");
|
DEBUG_ERROR("No configured display modes fit in transport memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,20 +224,20 @@ CDisplayConfiguration::SetResolution(
|
|||||||
ResolutionResult result;
|
ResolutionResult result;
|
||||||
|
|
||||||
UINT64 frameSize;
|
UINT64 frameSize;
|
||||||
UINT64 requiredIVSHMEMSize;
|
UINT64 requiredMemorySize;
|
||||||
if (!GetResolutionMemoryRequirements(width, height, limits.alignment,
|
if (!GetResolutionMemoryRequirements(width, height, limits.alignment,
|
||||||
limits, frameSize, requiredIVSHMEMSize))
|
limits, frameSize, requiredMemorySize))
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Ignoring invalid resolution request: %ux%u", width, height);
|
DEBUG_WARN("Ignoring invalid resolution request: %ux%u", width, height);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requiredIVSHMEMSize > limits.sharedSize)
|
if (requiredMemorySize > limits.capacity)
|
||||||
{
|
{
|
||||||
result.status = ResolutionStatus::TOO_LARGE;
|
result.status = ResolutionStatus::TOO_LARGE;
|
||||||
result.requiredMiB = RecommendedIVSHMEMSizeMiB(requiredIVSHMEMSize);
|
result.requiredMiB = RecommendedMemorySizeMiB(requiredMemorySize);
|
||||||
DEBUG_WARN(
|
DEBUG_WARN(
|
||||||
"Refusing resolution %ux%u: frame requires %llu bytes, only %llu bytes are available; IVSHMEM must be at least %u MiB",
|
"Refusing resolution %ux%u: frame requires %llu bytes, only %llu bytes are available; transport memory must be at least %u MiB",
|
||||||
width, height,
|
width, height,
|
||||||
(unsigned long long)frameSize,
|
(unsigned long long)frameSize,
|
||||||
(unsigned long long)limits.maxFrameSize,
|
(unsigned long long)limits.maxFrameSize,
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ private:
|
|||||||
UINT64& frameSize);
|
UINT64& frameSize);
|
||||||
static bool GetResolutionMemoryRequirements(uint32_t width,
|
static bool GetResolutionMemoryRequirements(uint32_t width,
|
||||||
uint32_t height, UINT64 alignment, const FrameMemoryLimits& limits,
|
uint32_t height, UINT64 alignment, const FrameMemoryLimits& limits,
|
||||||
UINT64& frameSize, UINT64& sharedSize);
|
UINT64& frameSize, UINT64& requiredSize);
|
||||||
static uint32_t RecommendedIVSHMEMSizeMiB(UINT64 requiredSize);
|
static uint32_t RecommendedMemorySizeMiB(UINT64 requiredSize);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CDisplayConfiguration(CSettings& settings);
|
explicit CDisplayConfiguration(CSettings& settings);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ private:
|
|||||||
IDDCX_MONITOR m_monitor = nullptr;
|
IDDCX_MONITOR m_monitor = nullptr;
|
||||||
|
|
||||||
// Guards the monitor/replug/swap-chain state. These values are touched by
|
// Guards the monitor/replug/swap-chain state. These values are touched by
|
||||||
// IddCx callback threads, the swap-chain thread, and the LGMP timer.
|
// IddCx callback threads, the swap-chain thread, and the transport timer.
|
||||||
SRWLOCK m_lock = SRWLOCK_INIT;
|
SRWLOCK m_lock = SRWLOCK_INIT;
|
||||||
|
|
||||||
bool m_replugMonitor = false;
|
bool m_replugMonitor = false;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "display/IddCxCompat.h"
|
#include "display/IddCxCompat.h"
|
||||||
#include "transport/CPipeServer.h"
|
#include "transport/CPipeServer.h"
|
||||||
|
#include "transport/IFrameTransport.h"
|
||||||
|
#include "transport/TransportFactory.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
#include <dxgi1_2.h>
|
#include <dxgi1_2.h>
|
||||||
@@ -33,8 +35,7 @@ static const UINT IDDCX_VERSION_1_10 = 0x1A00;
|
|||||||
|
|
||||||
CDeviceContext::CDeviceContext(WDFDEVICE wdfDevice) :
|
CDeviceContext::CDeviceContext(WDFDEVICE wdfDevice) :
|
||||||
m_wdfDevice(wdfDevice),
|
m_wdfDevice(wdfDevice),
|
||||||
m_lgmpControl(m_lgmpHost),
|
m_transport(CreateTransport()),
|
||||||
m_frameTransport(m_lgmpHost, m_ivshmem),
|
|
||||||
m_displayConfiguration(g_settings)
|
m_displayConfiguration(g_settings)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -49,10 +50,10 @@ CDeviceContext::~CDeviceContext()
|
|||||||
m_initTimer = nullptr;
|
m_initTimer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_lgmpTimer)
|
if (m_transportTimer)
|
||||||
{
|
{
|
||||||
WdfTimerStop(m_lgmpTimer, TRUE);
|
WdfTimerStop(m_transportTimer, TRUE);
|
||||||
m_lgmpTimer = nullptr;
|
m_transportTimer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,19 +157,32 @@ void CDeviceContext::InitAdapter()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At boot the IVSHMEM PCI device may not have enumerated yet. Rather than
|
// At boot the selected transport may not be available yet. Rather than
|
||||||
// silently abandoning the adapter (leaving the device loaded but with no
|
// silently abandoning the adapter (leaving the device loaded but with no
|
||||||
// monitor), retry from a timer until the shared memory becomes available.
|
// monitor), retry from a timer until it can be opened.
|
||||||
if (!m_ivshmemOpened)
|
if (!m_transportOpened)
|
||||||
{
|
{
|
||||||
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
if (!m_transport)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("IVSHMEM not available yet, scheduling init retry");
|
DEBUG_ERROR("Failed to create the frame transport");
|
||||||
ScheduleInitRetry();
|
|
||||||
m_initInProgress.store(0);
|
m_initInProgress.store(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_ivshmemOpened = true;
|
|
||||||
|
const ITransport::OpenResult result = m_transport->Open();
|
||||||
|
if (result != ITransport::OpenResult::SUCCESS)
|
||||||
|
{
|
||||||
|
if (result == ITransport::OpenResult::RETRY)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Frame transport not available yet, scheduling init retry");
|
||||||
|
ScheduleInitRetry();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DEBUG_ERROR("Failed to open the frame transport");
|
||||||
|
m_initInProgress.store(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_transportOpened = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select the render adapter before advertising capabilities. If no hardware
|
// Select the render adapter before advertising capabilities. If no hardware
|
||||||
@@ -234,14 +248,14 @@ void CDeviceContext::InitAdapter()
|
|||||||
DEBUG_INFO("No hardware render adapter available; using SDR software mode");
|
DEBUG_INFO("No hardware render adapter available; using SDR software mode");
|
||||||
|
|
||||||
QueryIddCxCapabilities();
|
QueryIddCxCapabilities();
|
||||||
DEBUG_TRACE("Initializing LGMP metadata");
|
DEBUG_TRACE("Initializing frame transport metadata");
|
||||||
if (!InitializeLGMP())
|
if (!InitializeTransport())
|
||||||
{
|
{
|
||||||
m_initInProgress.store(0);
|
m_initInProgress.store(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DEBUG_TRACE("Loading configured display modes");
|
DEBUG_TRACE("Loading configured display modes");
|
||||||
if (!m_displayConfiguration.Load(m_frameTransport.GetMemoryLimits()))
|
if (!m_displayConfiguration.Load(m_transport->GetMemoryLimits()))
|
||||||
{
|
{
|
||||||
m_initInProgress.store(0);
|
m_initInProgress.store(0);
|
||||||
return;
|
return;
|
||||||
@@ -374,7 +388,7 @@ void CDeviceContext::ReplugMonitor()
|
|||||||
void CDeviceContext::ReloadSettings()
|
void CDeviceContext::ReloadSettings()
|
||||||
{
|
{
|
||||||
if (!m_displayConfiguration.ReloadSettings(
|
if (!m_displayConfiguration.ReloadSettings(
|
||||||
m_frameTransport.GetMemoryLimits()))
|
m_transport->GetMemoryLimits()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ReplugMonitor();
|
ReplugMonitor();
|
||||||
@@ -417,7 +431,7 @@ void CDeviceContext::SetResolution(uint32_t width, uint32_t height)
|
|||||||
{
|
{
|
||||||
const CDisplayConfiguration::ResolutionResult result =
|
const CDisplayConfiguration::ResolutionResult result =
|
||||||
m_displayConfiguration.SetResolution(
|
m_displayConfiguration.SetResolution(
|
||||||
width, height, m_frameTransport.GetMemoryLimits());
|
width, height, m_transport->GetMemoryLimits());
|
||||||
|
|
||||||
switch (result.status)
|
switch (result.status)
|
||||||
{
|
{
|
||||||
@@ -437,33 +451,21 @@ void CDeviceContext::SetResolution(uint32_t width, uint32_t height)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LGMP transport
|
// Frame transport
|
||||||
|
|
||||||
bool CDeviceContext::InitializeLGMP()
|
bool CDeviceContext::InitializeTransport()
|
||||||
{
|
{
|
||||||
if (m_lgmpHost.IsInitialized())
|
return m_transport && m_transport->Initialize();
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!m_lgmpHost.Initialize(m_ivshmem))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Preserve the shared-memory layout: frame queues precede the pointer queue
|
|
||||||
// and its retained cursor and color-transform allocations.
|
|
||||||
if (!m_frameTransport.Initialize() || !m_lgmpControl.Initialize())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_frameTransport.SealMemoryLayout();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDeviceContext::SetupLGMP(size_t alignSize)
|
bool CDeviceContext::SetupTransport(size_t alignSize)
|
||||||
{
|
{
|
||||||
// Frame buffers cannot be allocated until the GPU-specific alignment is
|
// Frame buffers cannot be allocated until the GPU-specific alignment is
|
||||||
// known. The swap-chain path may call this again after setup completed.
|
// known. The swap-chain path may call this again after setup completed.
|
||||||
if (m_frameTransport.GetMaxFrameSize())
|
if (m_transport->Frames().GetMaxFrameSize())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!InitializeLGMP() || !m_frameTransport.Setup(alignSize))
|
if (!InitializeTransport() || !m_transport->Setup(alignSize))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
WDF_TIMER_CONFIG config;
|
WDF_TIMER_CONFIG config;
|
||||||
@@ -472,7 +474,7 @@ bool CDeviceContext::SetupLGMP(size_t alignSize)
|
|||||||
{
|
{
|
||||||
WDFOBJECT parent = WdfTimerGetParentObject(timer);
|
WDFOBJECT parent = WdfTimerGetParentObject(timer);
|
||||||
auto wrapper = WdfObjectGet_CDeviceContextWrapper(parent);
|
auto wrapper = WdfObjectGet_CDeviceContextWrapper(parent);
|
||||||
wrapper->context->LGMPTimer();
|
wrapper->context->TransportTimer();
|
||||||
},
|
},
|
||||||
10);
|
10);
|
||||||
config.AutomaticSerialization = FALSE;
|
config.AutomaticSerialization = FALSE;
|
||||||
@@ -487,18 +489,18 @@ bool CDeviceContext::SetupLGMP(size_t alignSize)
|
|||||||
attribs.ExecutionLevel = WdfExecutionLevelDispatch;
|
attribs.ExecutionLevel = WdfExecutionLevelDispatch;
|
||||||
|
|
||||||
NTSTATUS status = WdfTimerCreate(
|
NTSTATUS status = WdfTimerCreate(
|
||||||
&config, &attribs, &m_lgmpTimer);
|
&config, &attribs, &m_transportTimer);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR_HR(status, "Timer creation failed");
|
DEBUG_ERROR_HR(status, "Timer creation failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WdfTimerStart(m_lgmpTimer, WDF_REL_TIMEOUT_IN_MS(10));
|
WdfTimerStart(m_transportTimer, WDF_REL_TIMEOUT_IN_MS(10));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDeviceContext::LGMPTimer()
|
void CDeviceContext::TransportTimer()
|
||||||
{
|
{
|
||||||
// Monitor work is deferred off IddCx callback threads.
|
// Monitor work is deferred off IddCx callback threads.
|
||||||
switch (m_monitorManager.TakeDeferredAction())
|
switch (m_monitorManager.TakeDeferredAction())
|
||||||
@@ -515,74 +517,15 @@ void CDeviceContext::LGMPTimer()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LGMP_STATUS processStatus = m_lgmpHost.Process();
|
m_transport->Process(*this);
|
||||||
if (processStatus != LGMP_OK)
|
}
|
||||||
{
|
|
||||||
if (processStatus == LGMP_ERR_CORRUPTED)
|
void CDeviceContext::OnSetCursorPos(int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
DEBUG_WARN(
|
g_pipe.SetCursorPos(x, y);
|
||||||
"LGMP reported the shared memory has been corrupted, attempting to recover\n");
|
}
|
||||||
// TODO: reinitialize LGMP.
|
|
||||||
return;
|
void CDeviceContext::OnSetResolution(uint32_t width, uint32_t height)
|
||||||
}
|
{
|
||||||
|
SetResolution(width, height);
|
||||||
DEBUG_ERROR("lgmpHostProcess Failed: %s",
|
|
||||||
lgmpStatusString(processStatus));
|
|
||||||
// TODO: shut down LGMP.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint64_t now = CFrameScheduler::Nanotime();
|
|
||||||
|
|
||||||
// Take the frame subscriber snapshot before processing scheduling messages,
|
|
||||||
// then publish both updates together just as the original timer did.
|
|
||||||
const CFrameTransport::SubscriberSnapshot subscribers =
|
|
||||||
m_frameTransport.SnapshotSubscribers();
|
|
||||||
|
|
||||||
uint8_t data[LGMP_MSGS_SIZE];
|
|
||||||
size_t size;
|
|
||||||
uint32_t sourceClientID;
|
|
||||||
LGMP_STATUS status;
|
|
||||||
while ((status = m_lgmpControl.ReadDataWithSource(
|
|
||||||
data, &size, &sourceClientID)) == LGMP_OK)
|
|
||||||
{
|
|
||||||
KVMFRMessage * msg = reinterpret_cast<KVMFRMessage *>(data);
|
|
||||||
switch (msg->type)
|
|
||||||
{
|
|
||||||
case KVMFR_MESSAGE_SETCURSORPOS:
|
|
||||||
{
|
|
||||||
KVMFRSetCursorPos * position =
|
|
||||||
reinterpret_cast<KVMFRSetCursorPos *>(msg);
|
|
||||||
g_pipe.SetCursorPos(position->x, position->y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case KVMFR_MESSAGE_WINDOWSIZE:
|
|
||||||
{
|
|
||||||
KVMFRWindowSize * window =
|
|
||||||
reinterpret_cast<KVMFRWindowSize *>(msg);
|
|
||||||
SetResolution(window->w, window->h);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case KVMFR_MESSAGE_FRAME_SCHEDULE:
|
|
||||||
{
|
|
||||||
const KVMFRFrameSchedule * schedule =
|
|
||||||
reinterpret_cast<KVMFRFrameSchedule *>(msg);
|
|
||||||
const bool valid = size == sizeof(*schedule) &&
|
|
||||||
m_frameTransport.UpdateSchedule(
|
|
||||||
sourceClientID, *schedule, now);
|
|
||||||
if (!valid)
|
|
||||||
DEBUG_WARN("Ignoring invalid KVMFR frame schedule");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lgmpControl.AckData();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_frameTransport.FinalizeSubscribers(subscribers, now);
|
|
||||||
|
|
||||||
if (m_lgmpControl.HasNewSubscribers())
|
|
||||||
m_lgmpControl.ResendState();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,17 +25,15 @@
|
|||||||
#include <IddCx.h>
|
#include <IddCx.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "display/CDisplayConfiguration.h"
|
#include "display/CDisplayConfiguration.h"
|
||||||
#include "display/CMonitorManager.h"
|
#include "display/CMonitorManager.h"
|
||||||
#include "transport/CFrameTransport.h"
|
#include "transport/ITransport.h"
|
||||||
#include "transport/CIVSHMEM.h"
|
|
||||||
#include "transport/CLGMPControl.h"
|
|
||||||
#include "transport/CLGMPHost.h"
|
|
||||||
|
|
||||||
class CDeviceContext
|
class CDeviceContext : private ITransportEvents
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
WDFDEVICE m_wdfDevice;
|
WDFDEVICE m_wdfDevice;
|
||||||
@@ -43,20 +41,17 @@ private:
|
|||||||
LUID m_preferredRenderAdapter = {};
|
LUID m_preferredRenderAdapter = {};
|
||||||
bool m_havePreferredRenderAdapter = false;
|
bool m_havePreferredRenderAdapter = false;
|
||||||
|
|
||||||
// At boot IVSHMEM may not have enumerated yet. The retry timer and atomic
|
// At boot the selected transport may not be available yet. The retry timer
|
||||||
// gate keep adapter creation single-threaded until it becomes available.
|
// and atomic gate keep adapter creation single-threaded until it is ready.
|
||||||
WDFTIMER m_initTimer = nullptr;
|
WDFTIMER m_initTimer = nullptr;
|
||||||
bool m_ivshmemOpened = false;
|
bool m_transportOpened = false;
|
||||||
std::atomic<LONG> m_initInProgress = 0;
|
std::atomic<LONG> m_initInProgress = 0;
|
||||||
|
|
||||||
CIVSHMEM m_ivshmem;
|
std::unique_ptr<ITransport> m_transport;
|
||||||
CLGMPHost m_lgmpHost;
|
CDisplayConfiguration m_displayConfiguration;
|
||||||
CLGMPControl m_lgmpControl;
|
CMonitorManager m_monitorManager;
|
||||||
CFrameTransport m_frameTransport;
|
|
||||||
CDisplayConfiguration m_displayConfiguration;
|
|
||||||
CMonitorManager m_monitorManager;
|
|
||||||
|
|
||||||
WDFTIMER m_lgmpTimer = nullptr;
|
WDFTIMER m_transportTimer = nullptr;
|
||||||
|
|
||||||
UINT m_iddCxVersion = 0;
|
UINT m_iddCxVersion = 0;
|
||||||
bool m_hasIddCx110DDIs = false;
|
bool m_hasIddCx110DDIs = false;
|
||||||
@@ -68,8 +63,10 @@ private:
|
|||||||
void ScheduleInitRetry();
|
void ScheduleInitRetry();
|
||||||
void StopInitRetry();
|
void StopInitRetry();
|
||||||
|
|
||||||
bool InitializeLGMP();
|
bool InitializeTransport();
|
||||||
void LGMPTimer();
|
void TransportTimer();
|
||||||
|
void OnSetCursorPos(int32_t x, int32_t y) override;
|
||||||
|
void OnSetResolution(uint32_t width, uint32_t height) override;
|
||||||
void SetResolution(uint32_t width, uint32_t height);
|
void SetResolution(uint32_t width, uint32_t height);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -79,7 +76,7 @@ public:
|
|||||||
CDeviceContext(const CDeviceContext&) = delete;
|
CDeviceContext(const CDeviceContext&) = delete;
|
||||||
CDeviceContext& operator=(const CDeviceContext&) = delete;
|
CDeviceContext& operator=(const CDeviceContext&) = delete;
|
||||||
|
|
||||||
bool SetupLGMP(size_t alignSize);
|
bool SetupTransport(size_t alignSize);
|
||||||
|
|
||||||
void InitAdapter();
|
void InitAdapter();
|
||||||
void FinishAdapterInit(UINT connectorIndex);
|
void FinishAdapterInit(UINT connectorIndex);
|
||||||
@@ -96,14 +93,9 @@ public:
|
|||||||
bool CanProcessFP16 () const { return m_canProcessFP16; }
|
bool CanProcessFP16 () const { return m_canProcessFP16; }
|
||||||
bool IsSoftwareMode () const { return m_softwareMode; }
|
bool IsSoftwareMode () const { return m_softwareMode; }
|
||||||
|
|
||||||
CFrameTransport& GetFrameTransport()
|
ITransport& GetTransport()
|
||||||
{
|
{
|
||||||
return m_frameTransport;
|
return *m_transport;
|
||||||
}
|
|
||||||
|
|
||||||
CLGMPControl& GetLGMPControl()
|
|
||||||
{
|
|
||||||
return m_lgmpControl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CDisplayConfiguration& GetDisplayConfiguration()
|
CDisplayConfiguration& GetDisplayConfiguration()
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ NTSTATUS CMonitorContext::AssignSwapChain(
|
|||||||
|
|
||||||
// Build the D3D11 device into a local so the member is never observed
|
// Build the D3D11 device into a local so the member is never observed
|
||||||
// half-constructed. The worker binds it before performing the expensive
|
// half-constructed. The worker binds it before performing the expensive
|
||||||
// D3D12, LGMP and post-processing initialization.
|
// D3D12, transport and post-processing initialization.
|
||||||
auto dx11Device = std::make_shared<CD3D11Device>(renderAdapter);
|
auto dx11Device = std::make_shared<CD3D11Device>(renderAdapter);
|
||||||
const HRESULT initStatus = dx11Device->Init();
|
const HRESULT initStatus = dx11Device->Init();
|
||||||
if (FAILED(initStatus))
|
if (FAILED(initStatus))
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
#include "config/CSettings.h"
|
#include "config/CSettings.h"
|
||||||
#include "common/LGMPConfig.h"
|
#include "transport/TransportTypes.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
@@ -61,7 +61,7 @@ struct CRGB24Effect::State
|
|||||||
std::shared_ptr<const D12ColorTransform> colorTransform;
|
std::shared_ptr<const D12ColorTransform> colorTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned WarmupCount = LGMP_Q_FRAME_LEN;
|
static const unsigned WarmupCount = TRANSPORT_FRAME_QUEUE_LENGTH;
|
||||||
static const unsigned SampleCount = 64;
|
static const unsigned SampleCount = 64;
|
||||||
static const unsigned TrimCount = SampleCount / 8;
|
static const unsigned TrimCount = SampleCount / 8;
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "capture/CFrameScheduler.h"
|
#include "transport/CFrameScheduler.h"
|
||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
@@ -288,10 +288,10 @@ void CFrameScheduler::UpdateSubscribers(const uint32_t * clientIDs,
|
|||||||
{
|
{
|
||||||
AcquireSRWLockExclusive(&m_lock);
|
AcquireSRWLockExclusive(&m_lock);
|
||||||
|
|
||||||
uint32_t oldClientIDs [LGMP_MAX_CLIENTS] = {};
|
uint32_t oldClientIDs [TRANSPORT_MAX_CLIENTS] = {};
|
||||||
bool wasSubscribed [LGMP_MAX_CLIENTS] = {};
|
bool wasSubscribed [TRANSPORT_MAX_CLIENTS] = {};
|
||||||
bool wasOwnerCapable[LGMP_MAX_CLIENTS] = {};
|
bool wasOwnerCapable[TRANSPORT_MAX_CLIENTS] = {};
|
||||||
unsigned clientIndex = 0;
|
unsigned clientIndex = 0;
|
||||||
for (const Client& client : m_clients)
|
for (const Client& client : m_clients)
|
||||||
{
|
{
|
||||||
oldClientIDs[clientIndex] = client.clientID;
|
oldClientIDs[clientIndex] = client.clientID;
|
||||||
@@ -349,19 +349,19 @@ void CFrameScheduler::UpdateSubscribers(const uint32_t * clientIDs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
||||||
const KVMFRFrameSchedule& schedule, uint64_t now)
|
const FrameScheduleUpdate& schedule, uint64_t now)
|
||||||
{
|
{
|
||||||
static const KVMFRFrameScheduleFlags validFlags =
|
static const uint32_t validFlags =
|
||||||
KVMFR_FRAME_SCHEDULE_ACTIVE |
|
FRAME_SCHEDULE_ACTIVE |
|
||||||
KVMFR_FRAME_SCHEDULE_RELEASE |
|
FRAME_SCHEDULE_RELEASE |
|
||||||
KVMFR_FRAME_SCHEDULE_RESET |
|
FRAME_SCHEDULE_RESET |
|
||||||
KVMFR_FRAME_SCHEDULE_IMMEDIATE;
|
FRAME_SCHEDULE_IMMEDIATE;
|
||||||
|
|
||||||
if (!sourceClientID || schedule.clientID != sourceClientID ||
|
if (!sourceClientID || schedule.clientID != sourceClientID ||
|
||||||
schedule.flags & ~validFlags)
|
schedule.flags & ~validFlags)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (schedule.flags & KVMFR_FRAME_SCHEDULE_RELEASE)
|
if (schedule.flags & FRAME_SCHEDULE_RELEASE)
|
||||||
{
|
{
|
||||||
AcquireSRWLockExclusive(&m_lock);
|
AcquireSRWLockExclusive(&m_lock);
|
||||||
Client * client = FindClient(schedule.clientID);
|
Client * client = FindClient(schedule.clientID);
|
||||||
@@ -381,7 +381,7 @@ bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(schedule.flags & KVMFR_FRAME_SCHEDULE_ACTIVE) ||
|
if (!(schedule.flags & FRAME_SCHEDULE_ACTIVE) ||
|
||||||
schedule.period < MIN_SCHEDULE_PERIOD_NS ||
|
schedule.period < MIN_SCHEDULE_PERIOD_NS ||
|
||||||
schedule.period > MAX_PERIOD_NS ||
|
schedule.period > MAX_PERIOD_NS ||
|
||||||
schedule.targetSlack >= schedule.period ||
|
schedule.targetSlack >= schedule.period ||
|
||||||
@@ -400,7 +400,7 @@ bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool explicitReset =
|
const bool explicitReset =
|
||||||
(schedule.flags & KVMFR_FRAME_SCHEDULE_RESET) != 0;
|
(schedule.flags & FRAME_SCHEDULE_RESET) != 0;
|
||||||
const bool reset = client->generation != schedule.generation ||
|
const bool reset = client->generation != schedule.generation ||
|
||||||
explicitReset;
|
explicitReset;
|
||||||
bool wake = reset || !client->active ||
|
bool wake = reset || !client->active ||
|
||||||
@@ -417,7 +417,7 @@ bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
|||||||
client->targetSlack = schedule.targetSlack;
|
client->targetSlack = schedule.targetSlack;
|
||||||
client->expiry = now + static_cast<uint64_t>(schedule.lease) * 1000000;
|
client->expiry = now + static_cast<uint64_t>(schedule.lease) * 1000000;
|
||||||
client->active = true;
|
client->active = true;
|
||||||
if (schedule.flags & KVMFR_FRAME_SCHEDULE_IMMEDIATE)
|
if (schedule.flags & FRAME_SCHEDULE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
client->immediate = true;
|
client->immediate = true;
|
||||||
wake = true;
|
wake = true;
|
||||||
@@ -425,7 +425,7 @@ bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
|||||||
wake |= ElectOwner(now, explicitReset ? schedule.clientID : 0);
|
wake |= ElectOwner(now, explicitReset ? schedule.clientID : 0);
|
||||||
if (m_scheduling && client->clientID == m_schedule.clientID &&
|
if (m_scheduling && client->clientID == m_schedule.clientID &&
|
||||||
client->generation == m_schedule.generation &&
|
client->generation == m_schedule.generation &&
|
||||||
(schedule.flags & KVMFR_FRAME_SCHEDULE_IMMEDIATE))
|
(schedule.flags & FRAME_SCHEDULE_IMMEDIATE))
|
||||||
{
|
{
|
||||||
++m_forceRequestTicket;
|
++m_forceRequestTicket;
|
||||||
++m_republishRequestTicket;
|
++m_republishRequestTicket;
|
||||||
@@ -439,7 +439,7 @@ bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameScheduler::ApplyFeedback(Client& client,
|
bool CFrameScheduler::ApplyFeedback(Client& client,
|
||||||
const KVMFRFrameSchedule& schedule)
|
const FrameScheduleUpdate& schedule)
|
||||||
{
|
{
|
||||||
if (!m_scheduling || client.clientID != m_schedule.clientID ||
|
if (!m_scheduling || client.clientID != m_schedule.clientID ||
|
||||||
schedule.generation != m_schedule.generation ||
|
schedule.generation != m_schedule.generation ||
|
||||||
@@ -23,11 +23,7 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern "C" {
|
#include "transport/TransportTypes.h"
|
||||||
#include <lgmp/lgmp.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "common/KVMFR.h"
|
|
||||||
|
|
||||||
class CFrameScheduler
|
class CFrameScheduler
|
||||||
{
|
{
|
||||||
@@ -79,15 +75,15 @@ private:
|
|||||||
bool accepted;
|
bool accepted;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned PUBLICATION_HISTORY_SIZE = 128;
|
static const unsigned PUBLICATION_HISTORY_SIZE = 128;
|
||||||
static const unsigned WORK_TIMING_HISTORY_SIZE = 32;
|
static const unsigned WORK_TIMING_HISTORY_SIZE = 32;
|
||||||
|
|
||||||
mutable SRWLOCK m_lock = SRWLOCK_INIT;
|
mutable SRWLOCK m_lock = SRWLOCK_INIT;
|
||||||
HANDLE m_wakeEvent = nullptr;
|
HANDLE m_wakeEvent = nullptr;
|
||||||
Client m_clients[LGMP_MAX_CLIENTS] = {};
|
Client m_clients[TRANSPORT_MAX_CLIENTS] = {};
|
||||||
Schedule m_schedule = {};
|
Schedule m_schedule = {};
|
||||||
bool m_scheduling = false;
|
bool m_scheduling = false;
|
||||||
uint32_t m_epoch = 0;
|
uint32_t m_epoch = 0;
|
||||||
|
|
||||||
// A result acknowledges only the request tickets captured by its attempt.
|
// A result acknowledges only the request tickets captured by its attempt.
|
||||||
uint64_t m_forceRequestTicket = 0;
|
uint64_t m_forceRequestTicket = 0;
|
||||||
@@ -122,7 +118,7 @@ private:
|
|||||||
Publication * FindPublication(const Schedule& schedule,
|
Publication * FindPublication(const Schedule& schedule,
|
||||||
uint32_t frameSerial);
|
uint32_t frameSerial);
|
||||||
bool ElectOwner(uint64_t now, uint32_t resetClientID = 0);
|
bool ElectOwner(uint64_t now, uint32_t resetClientID = 0);
|
||||||
bool ApplyFeedback(Client& client, const KVMFRFrameSchedule& schedule);
|
bool ApplyFeedback(Client& client, const FrameScheduleUpdate& schedule);
|
||||||
void AdvanceCurrentDeadline();
|
void AdvanceCurrentDeadline();
|
||||||
void AdvanceDeadlineSerial(uint64_t count);
|
void AdvanceDeadlineSerial(uint64_t count);
|
||||||
void AdvanceDeadline(uint64_t now);
|
void AdvanceDeadline(uint64_t now);
|
||||||
@@ -139,7 +135,7 @@ public:
|
|||||||
void UpdateSubscribers(const uint32_t * clientIDs, unsigned count,
|
void UpdateSubscribers(const uint32_t * clientIDs, unsigned count,
|
||||||
const uint32_t * ownerClientIDs, unsigned ownerCount, uint64_t now);
|
const uint32_t * ownerClientIDs, unsigned ownerCount, uint64_t now);
|
||||||
bool UpdateSchedule(uint32_t sourceClientID,
|
bool UpdateSchedule(uint32_t sourceClientID,
|
||||||
const KVMFRFrameSchedule& schedule, uint64_t now);
|
const FrameScheduleUpdate& schedule, uint64_t now);
|
||||||
bool GetSchedule(Schedule& schedule) const;
|
bool GetSchedule(Schedule& schedule) const;
|
||||||
HANDLE GetWakeEvent() const { return m_wakeEvent; }
|
HANDLE GetWakeEvent() const { return m_wakeEvent; }
|
||||||
void ObserveFrame(uint64_t now);
|
void ObserveFrame(uint64_t now);
|
||||||
@@ -22,19 +22,10 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// FrameBuffer overlays LGMP shared memory and has a variable-length payload.
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable: 4200)
|
|
||||||
struct FrameBuffer
|
|
||||||
{
|
|
||||||
volatile uint32_t wp;
|
|
||||||
uint8_t data[0];
|
|
||||||
};
|
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
struct PreparedFrameBuffer
|
struct PreparedFrameBuffer
|
||||||
{
|
{
|
||||||
unsigned frameIndex;
|
unsigned frameIndex;
|
||||||
uint8_t * mem;
|
uint8_t * mem;
|
||||||
|
uint64_t heapOffset;
|
||||||
bool fullCopy;
|
bool fullCopy;
|
||||||
};
|
};
|
||||||
@@ -24,8 +24,9 @@
|
|||||||
|
|
||||||
struct FrameMemoryLimits
|
struct FrameMemoryLimits
|
||||||
{
|
{
|
||||||
uint64_t sharedSize = 0;
|
uint64_t capacity = 0;
|
||||||
uint64_t frameMemoryOffset = 0;
|
uint64_t frameMemoryOffset = 0;
|
||||||
uint64_t alignment = 0;
|
uint64_t alignment = 0;
|
||||||
uint64_t maxFrameSize = 0;
|
uint64_t maxFrameSize = 0;
|
||||||
|
unsigned bufferCount = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
42
idd/LGIdd/transport/IControlTransport.h
Normal file
42
idd/LGIdd/transport/IControlTransport.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "postprocess/D12FrameFormat.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <wdf.h>
|
||||||
|
#include <IddCx.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class IControlTransport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IControlTransport() = default;
|
||||||
|
|
||||||
|
virtual void SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info,
|
||||||
|
const BYTE * data, UINT sdrWhiteLevel) = 0;
|
||||||
|
virtual void SetColorTransform(
|
||||||
|
std::shared_ptr<const D12ColorTransform> transform) = 0;
|
||||||
|
virtual std::shared_ptr<const D12ColorTransform>
|
||||||
|
GetColorTransform() const = 0;
|
||||||
|
};
|
||||||
87
idd/LGIdd/transport/IFrameTransport.h
Normal file
87
idd/LGIdd/transport/IFrameTransport.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "postprocess/D12FrameFormat.h"
|
||||||
|
#include "transport/CFrameScheduler.h"
|
||||||
|
#include "transport/FrameBufferTypes.h"
|
||||||
|
#include "transport/TransportTypes.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class IFrameTransport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IFrameTransport() = default;
|
||||||
|
|
||||||
|
virtual size_t GetMaxFrameSize() const = 0;
|
||||||
|
|
||||||
|
virtual bool FrameBufferAvailable(
|
||||||
|
const CFrameScheduler::Schedule& schedule,
|
||||||
|
bool allowReadyReplacement = true) = 0;
|
||||||
|
virtual bool HasPublishedFrame() const = 0;
|
||||||
|
virtual void ProcessDeliveries() = 0;
|
||||||
|
virtual bool GetPendingDeliveryTarget(
|
||||||
|
uint64_t now, uint64_t& target) = 0;
|
||||||
|
virtual bool RetryPendingDelivery(uint64_t now, bool& retry) = 0;
|
||||||
|
virtual PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch,
|
||||||
|
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
|
||||||
|
const RECT * dirtyRects, unsigned nbDirtyRects,
|
||||||
|
const CFrameScheduler::Schedule& schedule,
|
||||||
|
bool allowReadyReplacement = true) = 0;
|
||||||
|
virtual bool PublishFrameBuffer(unsigned frameIndex,
|
||||||
|
const CFrameScheduler::Schedule& schedule,
|
||||||
|
bool& deliveredToOwner) = 0;
|
||||||
|
virtual bool RepublishFrameBuffer(
|
||||||
|
const CFrameScheduler::Schedule& schedule) = 0;
|
||||||
|
virtual bool TryFrameSubmitted(unsigned frameIndex,
|
||||||
|
const CFrameScheduler::Schedule& schedule) = 0;
|
||||||
|
virtual void CommitFrameBuffer(unsigned frameIndex,
|
||||||
|
const CFrameScheduler::Schedule& schedule, bool periodic,
|
||||||
|
bool deliveredToOwner) = 0;
|
||||||
|
virtual void AbortFrameBuffer(unsigned frameIndex) = 0;
|
||||||
|
virtual void FailFrameBuffer(unsigned frameIndex) = 0;
|
||||||
|
virtual void CompleteFrameBuffer(
|
||||||
|
unsigned frameIndex, bool succeeded) = 0;
|
||||||
|
virtual void SetFrameTiming(unsigned frameIndex, uint64_t captureTime,
|
||||||
|
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
|
||||||
|
uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
|
||||||
|
uint64_t completedAt) = 0;
|
||||||
|
virtual void WriteFrameBuffer(unsigned frameIndex, void * src,
|
||||||
|
size_t offset, size_t len, bool setWritePos) const = 0;
|
||||||
|
virtual void WriteFrameBufferRows(unsigned frameIndex, void * src,
|
||||||
|
size_t offset, size_t rowBytes, size_t pitch,
|
||||||
|
unsigned rows) const = 0;
|
||||||
|
virtual void FinalizeFrameBuffer(unsigned frameIndex) const = 0;
|
||||||
|
|
||||||
|
virtual void ObserveFrame(uint64_t now) = 0;
|
||||||
|
virtual void ForceFrame() = 0;
|
||||||
|
virtual bool GetPublishTarget(uint64_t now, uint64_t& target,
|
||||||
|
CFrameScheduler::Schedule& schedule, bool& periodic,
|
||||||
|
bool& republish) = 0;
|
||||||
|
virtual void FrameMissed(const CFrameScheduler::Schedule& schedule,
|
||||||
|
uint64_t now, bool periodic) = 0;
|
||||||
|
virtual void FrameSuperseded() = 0;
|
||||||
|
virtual HANDLE GetFrameScheduleEvent() const = 0;
|
||||||
|
virtual void TryRecordFrameTiming(uint64_t duration) = 0;
|
||||||
|
};
|
||||||
63
idd/LGIdd/transport/ITransport.h
Normal file
63
idd/LGIdd/transport/ITransport.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "transport/FrameMemoryLimits.h"
|
||||||
|
#include "transport/TransportTypes.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class IControlTransport;
|
||||||
|
class IFrameTransport;
|
||||||
|
|
||||||
|
class ITransportEvents
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~ITransportEvents() = default;
|
||||||
|
|
||||||
|
virtual void OnSetCursorPos(int32_t x, int32_t y) = 0;
|
||||||
|
virtual void OnSetResolution(uint32_t width, uint32_t height) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ITransport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class OpenResult
|
||||||
|
{
|
||||||
|
SUCCESS,
|
||||||
|
RETRY,
|
||||||
|
FAILURE,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~ITransport() = default;
|
||||||
|
|
||||||
|
virtual OpenResult Open() = 0;
|
||||||
|
virtual bool Initialize() = 0;
|
||||||
|
virtual bool Setup(size_t alignment) = 0;
|
||||||
|
virtual void Process(ITransportEvents& events) = 0;
|
||||||
|
|
||||||
|
virtual FrameMemoryLimits GetMemoryLimits() const = 0;
|
||||||
|
virtual DirectFrameBufferMemory GetDirectMemory() const = 0;
|
||||||
|
|
||||||
|
virtual IFrameTransport& Frames() = 0;
|
||||||
|
virtual IControlTransport& Control() = 0;
|
||||||
|
};
|
||||||
30
idd/LGIdd/transport/TransportFactory.cpp
Normal file
30
idd/LGIdd/transport/TransportFactory.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "transport/TransportFactory.h"
|
||||||
|
|
||||||
|
#include "transport/lgmp/CLGMPTransport.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
std::unique_ptr<ITransport> CreateTransport()
|
||||||
|
{
|
||||||
|
return std::unique_ptr<ITransport>(new (std::nothrow) CLGMPTransport());
|
||||||
|
}
|
||||||
27
idd/LGIdd/transport/TransportFactory.h
Normal file
27
idd/LGIdd/transport/TransportFactory.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "transport/ITransport.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
std::unique_ptr<ITransport> CreateTransport();
|
||||||
64
idd/LGIdd/transport/TransportTypes.h
Normal file
64
idd/LGIdd/transport/TransportTypes.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum : unsigned
|
||||||
|
{
|
||||||
|
TRANSPORT_FRAME_QUEUE_LENGTH = 2,
|
||||||
|
TRANSPORT_FRAME_BUFFER_COUNT = 3,
|
||||||
|
TRANSPORT_MAX_CLIENTS = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum : uint32_t
|
||||||
|
{
|
||||||
|
FRAME_SCHEDULE_ACTIVE = 0x1,
|
||||||
|
FRAME_SCHEDULE_RELEASE = 0x2,
|
||||||
|
FRAME_SCHEDULE_RESET = 0x4,
|
||||||
|
FRAME_SCHEDULE_IMMEDIATE = 0x8,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FrameScheduleUpdate
|
||||||
|
{
|
||||||
|
uint32_t clientID;
|
||||||
|
uint32_t generation;
|
||||||
|
uint32_t flags;
|
||||||
|
uint64_t period;
|
||||||
|
uint64_t targetSlack;
|
||||||
|
int64_t phaseError;
|
||||||
|
uint32_t feedbackFrameSerial;
|
||||||
|
uint32_t feedbackScheduleEpoch;
|
||||||
|
uint32_t feedbackDeadlineSerial;
|
||||||
|
uint32_t lease;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DirectFrameBufferMemory
|
||||||
|
{
|
||||||
|
void * address = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
explicit operator bool() const
|
||||||
|
{
|
||||||
|
return address && size;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "transport/CIVSHMEM.h"
|
#include "transport/lgmp/CIVSHMEM.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <SetupAPI.h>
|
#include <SetupAPI.h>
|
||||||
@@ -47,5 +47,5 @@ public:
|
|||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
size_t GetSize() const { return m_size; }
|
size_t GetSize() const { return m_size; }
|
||||||
void * GetMem () { return m_mem; }
|
void * GetMem () const { return m_mem; }
|
||||||
};
|
};
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "transport/CLGMPControl.h"
|
#include "transport/lgmp/CLGMPControl.h"
|
||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "transport/CLGMPHost.h"
|
#include "transport/lgmp/CLGMPHost.h"
|
||||||
#include "postprocess/D12FrameFormat.h"
|
#include "transport/IControlTransport.h"
|
||||||
|
|
||||||
#include "common/KVMFR.h"
|
#include "common/KVMFR.h"
|
||||||
|
|
||||||
@@ -31,9 +31,13 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class CLGMPControl
|
class CLGMPTransport;
|
||||||
|
|
||||||
|
class CLGMPControl final : public IControlTransport
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
friend class CLGMPTransport;
|
||||||
|
|
||||||
static constexpr int POINTER_SHAPE_BUFFERS = 3;
|
static constexpr int POINTER_SHAPE_BUFFERS = 3;
|
||||||
static constexpr int COLOR_TRANSFORM_BUFFERS = 3;
|
static constexpr int COLOR_TRANSFORM_BUFFERS = 3;
|
||||||
|
|
||||||
@@ -56,27 +60,26 @@ private:
|
|||||||
|
|
||||||
void SendColorTransform();
|
void SendColorTransform();
|
||||||
void ResendCursor();
|
void ResendCursor();
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CLGMPControl(CLGMPHost& host) :
|
|
||||||
m_host(host) {}
|
|
||||||
~CLGMPControl();
|
|
||||||
|
|
||||||
CLGMPControl(const CLGMPControl&) = delete;
|
|
||||||
CLGMPControl& operator=(const CLGMPControl&) = delete;
|
|
||||||
|
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
LGMP_STATUS ReadDataWithSource(void * data, size_t * size,
|
LGMP_STATUS ReadDataWithSource(void * data, size_t * size,
|
||||||
uint32_t * sourceClientID);
|
uint32_t * sourceClientID);
|
||||||
LGMP_STATUS AckData();
|
LGMP_STATUS AckData();
|
||||||
bool HasNewSubscribers();
|
bool HasNewSubscribers();
|
||||||
|
void ResendState();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CLGMPControl(CLGMPHost& host) :
|
||||||
|
m_host(host) {}
|
||||||
|
~CLGMPControl() override;
|
||||||
|
|
||||||
|
CLGMPControl(const CLGMPControl&) = delete;
|
||||||
|
CLGMPControl& operator=(const CLGMPControl&) = delete;
|
||||||
|
|
||||||
void SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info, const BYTE * data,
|
void SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info, const BYTE * data,
|
||||||
UINT sdrWhiteLevel);
|
UINT sdrWhiteLevel) override;
|
||||||
void SetColorTransform(
|
void SetColorTransform(
|
||||||
std::shared_ptr<const D12ColorTransform> transform);
|
std::shared_ptr<const D12ColorTransform> transform) override;
|
||||||
std::shared_ptr<const D12ColorTransform> GetColorTransform() const;
|
std::shared_ptr<const D12ColorTransform>
|
||||||
void ResendState();
|
GetColorTransform() const override;
|
||||||
};
|
};
|
||||||
@@ -18,14 +18,30 @@
|
|||||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "transport/CFrameTransport.h"
|
#include "transport/lgmp/CLGMPFrameTransport.h"
|
||||||
|
|
||||||
#include "transport/CIVSHMEM.h"
|
#include "transport/lgmp/CIVSHMEM.h"
|
||||||
#include "transport/CLGMPHost.h"
|
#include "transport/lgmp/CLGMPHost.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4200)
|
||||||
|
struct LGMPBuffer
|
||||||
|
{
|
||||||
|
volatile uint32_t wp;
|
||||||
|
uint8_t data[0];
|
||||||
|
};
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
static_assert(TRANSPORT_FRAME_QUEUE_LENGTH == LGMP_Q_FRAME_LEN,
|
||||||
|
"The capture pipeline must match the LGMP frame queue");
|
||||||
|
static_assert(TRANSPORT_FRAME_BUFFER_COUNT == LGMP_Q_FRAME_BUFFER_LEN,
|
||||||
|
"The capture buffer pool must match the LGMP frame buffers");
|
||||||
|
static_assert(TRANSPORT_MAX_CLIENTS == LGMP_MAX_CLIENTS,
|
||||||
|
"The scheduler must support every LGMP client");
|
||||||
|
|
||||||
static const struct LGMPQueueConfig FRAME_QUEUE_CONFIG =
|
static const struct LGMPQueueConfig FRAME_QUEUE_CONFIG =
|
||||||
{
|
{
|
||||||
LGMP_Q_FRAME, // queueID
|
LGMP_Q_FRAME, // queueID
|
||||||
@@ -49,19 +65,19 @@ static bool FrameScheduleMatches(
|
|||||||
a.epoch == b.epoch;
|
a.epoch == b.epoch;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrameTransport::CFrameTransport(
|
CLGMPFrameTransport::CLGMPFrameTransport(
|
||||||
CLGMPHost& host, CIVSHMEM& ivshmem) :
|
CLGMPHost& host, CIVSHMEM& ivshmem) :
|
||||||
m_host(host),
|
m_host(host),
|
||||||
m_ivshmem(ivshmem)
|
m_ivshmem(ivshmem)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrameTransport::~CFrameTransport()
|
CLGMPFrameTransport::~CLGMPFrameTransport()
|
||||||
{
|
{
|
||||||
DeInit();
|
DeInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::Initialize()
|
bool CLGMPFrameTransport::Initialize()
|
||||||
{
|
{
|
||||||
if (m_frameQueue)
|
if (m_frameQueue)
|
||||||
{
|
{
|
||||||
@@ -100,13 +116,13 @@ bool CFrameTransport::Initialize()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::SealMemoryLayout()
|
void CLGMPFrameTransport::SealMemoryLayout()
|
||||||
{
|
{
|
||||||
m_frameMemoryOffset =
|
m_frameMemoryOffset =
|
||||||
m_ivshmem.GetSize() - m_host.Available();
|
m_ivshmem.GetSize() - m_host.Available();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::Setup(size_t alignSize)
|
bool CLGMPFrameTransport::Setup(size_t alignSize)
|
||||||
{
|
{
|
||||||
// This may get called multiple times as frame buffers cannot be allocated
|
// This may get called multiple times as frame buffers cannot be allocated
|
||||||
// until the GPU-specific alignment is known.
|
// until the GPU-specific alignment is known.
|
||||||
@@ -116,7 +132,7 @@ bool CFrameTransport::Setup(size_t alignSize)
|
|||||||
m_alignSize = alignSize;
|
m_alignSize = alignSize;
|
||||||
|
|
||||||
if (!m_alignSize || (m_alignSize & (m_alignSize - 1)) ||
|
if (!m_alignSize || (m_alignSize & (m_alignSize - 1)) ||
|
||||||
m_alignSize < sizeof(KVMFRFrame) + sizeof(FrameBuffer))
|
m_alignSize < sizeof(KVMFRFrame) + sizeof(LGMPBuffer))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Invalid frame buffer alignment: %llu",
|
DEBUG_ERROR("Invalid frame buffer alignment: %llu",
|
||||||
(unsigned long long)m_alignSize);
|
(unsigned long long)m_alignSize);
|
||||||
@@ -147,7 +163,7 @@ bool CFrameTransport::Setup(size_t alignSize)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The KVMFR frame header and FrameBuffer write position occupy the first
|
// The KVMFR frame header and frame-buffer write position occupy the first
|
||||||
// alignment unit. Only the bytes after it are usable for pixel data.
|
// alignment unit. Only the bytes after it are usable for pixel data.
|
||||||
const size_t maxFrameSize = frameAllocationSize - m_alignSize;
|
const size_t maxFrameSize = frameAllocationSize - m_alignSize;
|
||||||
DEBUG_INFO("Max Frame Data Size: %u MiB",
|
DEBUG_INFO("Max Frame Data Size: %u MiB",
|
||||||
@@ -173,9 +189,9 @@ bool CFrameTransport::Setup(size_t alignSize)
|
|||||||
* Put the framebuffer on the border of the next page, this is to allow
|
* Put the framebuffer on the border of the next page, this is to allow
|
||||||
* for aligned DMA transfers by the receiver.
|
* for aligned DMA transfers by the receiver.
|
||||||
*/
|
*/
|
||||||
const size_t alignOffset = alignSize - sizeof(FrameBuffer);
|
const size_t alignOffset = alignSize - sizeof(LGMPBuffer);
|
||||||
m_frame[i]->offset = (uint32_t)alignOffset;
|
m_frame[i]->offset = (uint32_t)alignOffset;
|
||||||
m_frameBuffer[i] = reinterpret_cast<FrameBuffer *>(
|
m_frameBuffer[i] = reinterpret_cast<LGMPBuffer *>(
|
||||||
reinterpret_cast<uint8_t *>(m_frame[i]) + alignOffset);
|
reinterpret_cast<uint8_t *>(m_frame[i]) + alignOffset);
|
||||||
m_frameInFlight[i].store(false, std::memory_order_release);
|
m_frameInFlight[i].store(false, std::memory_order_release);
|
||||||
m_frameCompleted[i] = false;
|
m_frameCompleted[i] = false;
|
||||||
@@ -196,7 +212,7 @@ bool CFrameTransport::Setup(size_t alignSize)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::DeInit()
|
void CLGMPFrameTransport::DeInit()
|
||||||
{
|
{
|
||||||
m_frameScheduler.Reset();
|
m_frameScheduler.Reset();
|
||||||
|
|
||||||
@@ -226,18 +242,19 @@ void CFrameTransport::DeInit()
|
|||||||
memset(m_frameOwnerQueue, 0, sizeof(m_frameOwnerQueue));
|
memset(m_frameOwnerQueue, 0, sizeof(m_frameOwnerQueue));
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameMemoryLimits CFrameTransport::GetMemoryLimits() const
|
FrameMemoryLimits CLGMPFrameTransport::GetMemoryLimits() const
|
||||||
{
|
{
|
||||||
FrameMemoryLimits limits;
|
FrameMemoryLimits limits;
|
||||||
limits.sharedSize = m_ivshmem.GetSize();
|
limits.capacity = m_ivshmem.GetSize();
|
||||||
limits.frameMemoryOffset = m_frameMemoryOffset;
|
limits.frameMemoryOffset = m_frameMemoryOffset;
|
||||||
limits.alignment = m_alignSize;
|
limits.alignment = m_alignSize;
|
||||||
limits.maxFrameSize = m_maxFrameSize;
|
limits.maxFrameSize = m_maxFrameSize;
|
||||||
|
limits.bufferCount = LGMP_Q_FRAME_BUFFER_LEN;
|
||||||
return limits;
|
return limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrameTransport::SubscriberSnapshot
|
CLGMPFrameTransport::SubscriberSnapshot
|
||||||
CFrameTransport::SnapshotSubscribers() const
|
CLGMPFrameTransport::SnapshotSubscribers() const
|
||||||
{
|
{
|
||||||
SubscriberSnapshot snapshot;
|
SubscriberSnapshot snapshot;
|
||||||
snapshot.status = lgmpHostGetClientIDs(
|
snapshot.status = lgmpHostGetClientIDs(
|
||||||
@@ -276,7 +293,7 @@ CFrameTransport::SnapshotSubscribers() const
|
|||||||
return snapshot;
|
return snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::FinalizeSubscribers(
|
void CLGMPFrameTransport::FinalizeSubscribers(
|
||||||
const SubscriberSnapshot& snapshot, uint64_t now)
|
const SubscriberSnapshot& snapshot, uint64_t now)
|
||||||
{
|
{
|
||||||
if (snapshot.status == LGMP_OK)
|
if (snapshot.status == LGMP_OK)
|
||||||
@@ -303,14 +320,14 @@ void CFrameTransport::FinalizeSubscribers(
|
|||||||
ProcessFrameDeliveries();
|
ProcessFrameDeliveries();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::UpdateSchedule(uint32_t sourceClientID,
|
bool CLGMPFrameTransport::UpdateSchedule(uint32_t sourceClientID,
|
||||||
const KVMFRFrameSchedule& schedule, uint64_t now)
|
const FrameScheduleUpdate& schedule, uint64_t now)
|
||||||
{
|
{
|
||||||
return m_frameScheduler.UpdateSchedule(sourceClientID, schedule, now);
|
return m_frameScheduler.UpdateSchedule(sourceClientID, schedule, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrameTransport::SharedFramePostResult
|
CLGMPFrameTransport::SharedFramePostResult
|
||||||
CFrameTransport::PostSharedFrame(unsigned frameIndex,
|
CLGMPFrameTransport::PostSharedFrame(unsigned frameIndex,
|
||||||
uint32_t excludeClientID, uint64_t now)
|
uint32_t excludeClientID, uint64_t now)
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN ||
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN ||
|
||||||
@@ -391,7 +408,7 @@ CFrameTransport::PostSharedFrame(unsigned frameIndex,
|
|||||||
return SHARED_FRAME_POSTED;
|
return SHARED_FRAME_POSTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::PostSharedOwnerFrame(unsigned frameIndex,
|
bool CLGMPFrameTransport::PostSharedOwnerFrame(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule)
|
const CFrameScheduler::Schedule& schedule)
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN || !schedule.clientID ||
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN || !schedule.clientID ||
|
||||||
@@ -419,7 +436,7 @@ bool CFrameTransport::PostSharedOwnerFrame(unsigned frameIndex,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::ProcessFrameDeliveries()
|
void CLGMPFrameTransport::ProcessFrameDeliveries()
|
||||||
{
|
{
|
||||||
if (!m_frameQueue)
|
if (!m_frameQueue)
|
||||||
return;
|
return;
|
||||||
@@ -471,7 +488,7 @@ void CFrameTransport::ProcessFrameDeliveries()
|
|||||||
m_frameScheduler.NotifyPublisher();
|
m_frameScheduler.NotifyPublisher();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CFrameTransport::FindAvailableOwnerQueue(
|
int CLGMPFrameTransport::FindAvailableOwnerQueue(
|
||||||
unsigned preferredIndex) const
|
unsigned preferredIndex) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
for (unsigned i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||||
@@ -487,7 +504,7 @@ int CFrameTransport::FindAvailableOwnerQueue(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned CFrameTransport::CountOwnerDeliveries(
|
unsigned CLGMPFrameTransport::CountOwnerDeliveries(
|
||||||
uint32_t clientID) const
|
uint32_t clientID) const
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
@@ -503,7 +520,7 @@ unsigned CFrameTransport::CountOwnerDeliveries(
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::HasMatchingOwnerDelivery(
|
bool CLGMPFrameTransport::HasMatchingOwnerDelivery(
|
||||||
uint32_t clientID, unsigned frameIndex, uint64_t token) const
|
uint32_t clientID, unsigned frameIndex, uint64_t token) const
|
||||||
{
|
{
|
||||||
for (const OwnerDelivery& delivery : m_ownerDelivery)
|
for (const OwnerDelivery& delivery : m_ownerDelivery)
|
||||||
@@ -526,7 +543,7 @@ bool CFrameTransport::HasMatchingOwnerDelivery(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::FrameBufferReferenced(
|
bool CLGMPFrameTransport::FrameBufferReferenced(
|
||||||
unsigned frameIndex) const
|
unsigned frameIndex) const
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
||||||
@@ -548,7 +565,7 @@ bool CFrameTransport::FrameBufferReferenced(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CFrameTransport::FindAvailableFrameBuffer(
|
int CLGMPFrameTransport::FindAvailableFrameBuffer(
|
||||||
bool allowReady) const
|
bool allowReady) const
|
||||||
{
|
{
|
||||||
const LONG readyFrameIndex =
|
const LONG readyFrameIndex =
|
||||||
@@ -582,7 +599,7 @@ int CFrameTransport::FindAvailableFrameBuffer(
|
|||||||
return static_cast<int>(readyFrameIndex);
|
return static_cast<int>(readyFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CFrameTransport::FindNewestCompletedFrame(
|
int CLGMPFrameTransport::FindNewestCompletedFrame(
|
||||||
unsigned excludeFrameIndex) const
|
unsigned excludeFrameIndex) const
|
||||||
{
|
{
|
||||||
int newestFrame = -1;
|
int newestFrame = -1;
|
||||||
@@ -605,7 +622,7 @@ int CFrameTransport::FindNewestCompletedFrame(
|
|||||||
return newestFrame;
|
return newestFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::FrameBufferAvailable(
|
bool CLGMPFrameTransport::FrameBufferAvailable(
|
||||||
const CFrameScheduler::Schedule& schedule,
|
const CFrameScheduler::Schedule& schedule,
|
||||||
bool allowReadyReplacement)
|
bool allowReadyReplacement)
|
||||||
{
|
{
|
||||||
@@ -642,7 +659,7 @@ bool CFrameTransport::FrameBufferAvailable(
|
|||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::ProcessFrameQueue()
|
void CLGMPFrameTransport::ProcessDeliveries()
|
||||||
{
|
{
|
||||||
if (!m_host.IsInitialized())
|
if (!m_host.IsInitialized())
|
||||||
return;
|
return;
|
||||||
@@ -656,7 +673,7 @@ void CFrameTransport::ProcessFrameQueue()
|
|||||||
ProcessFrameDeliveries();
|
ProcessFrameDeliveries();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::GetSharedFrameTarget(uint64_t now,
|
bool CLGMPFrameTransport::GetPendingDeliveryTarget(uint64_t now,
|
||||||
uint64_t& target)
|
uint64_t& target)
|
||||||
{
|
{
|
||||||
if (!m_frameQueue)
|
if (!m_frameQueue)
|
||||||
@@ -686,7 +703,7 @@ bool CFrameTransport::GetSharedFrameTarget(uint64_t now,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::ReplaySharedFrame(uint64_t now, bool& retry)
|
bool CLGMPFrameTransport::RetryPendingDelivery(uint64_t now, bool& retry)
|
||||||
{
|
{
|
||||||
retry = false;
|
retry = false;
|
||||||
if (!m_frameQueue)
|
if (!m_frameQueue)
|
||||||
@@ -710,7 +727,7 @@ bool CFrameTransport::ReplaySharedFrame(uint64_t now, bool& retry)
|
|||||||
return result == SHARED_FRAME_POSTED;
|
return result == SHARED_FRAME_POSTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreparedFrameBuffer CFrameTransport::PrepareFrameBuffer(
|
PreparedFrameBuffer CLGMPFrameTransport::PrepareFrameBuffer(
|
||||||
unsigned pitch, const D12FrameFormat& srcFormat,
|
unsigned pitch, const D12FrameFormat& srcFormat,
|
||||||
const D12FrameFormat& dstFormat, const RECT * dirtyRects,
|
const D12FrameFormat& dstFormat, const RECT * dirtyRects,
|
||||||
unsigned nbDirtyRects, const CFrameScheduler::Schedule& schedule,
|
unsigned nbDirtyRects, const CFrameScheduler::Schedule& schedule,
|
||||||
@@ -903,16 +920,18 @@ PreparedFrameBuffer CFrameTransport::PrepareFrameBuffer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameBuffer * fb = m_frameBuffer[frameIndex];
|
LGMPBuffer * fb = m_frameBuffer[frameIndex];
|
||||||
fb->wp = 0;
|
fb->wp = 0;
|
||||||
|
|
||||||
result.frameIndex = frameIndex;
|
result.frameIndex = frameIndex;
|
||||||
result.mem = fb->data;
|
result.mem = fb->data;
|
||||||
|
result.heapOffset = reinterpret_cast<uintptr_t>(fb->data) -
|
||||||
|
reinterpret_cast<uintptr_t>(m_ivshmem.GetMem());
|
||||||
result.fullCopy = fullCopy;
|
result.fullCopy = fullCopy;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::PublishFrameBuffer(unsigned frameIndex,
|
bool CLGMPFrameTransport::PublishFrameBuffer(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule, bool& deliveredToOwner)
|
const CFrameScheduler::Schedule& schedule, bool& deliveredToOwner)
|
||||||
{
|
{
|
||||||
deliveredToOwner = false;
|
deliveredToOwner = false;
|
||||||
@@ -1017,7 +1036,7 @@ bool CFrameTransport::PublishFrameBuffer(unsigned frameIndex,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::RepublishFrameBuffer(
|
bool CLGMPFrameTransport::RepublishFrameBuffer(
|
||||||
const CFrameScheduler::Schedule& schedule)
|
const CFrameScheduler::Schedule& schedule)
|
||||||
{
|
{
|
||||||
if (!schedule.clientID)
|
if (!schedule.clientID)
|
||||||
@@ -1118,7 +1137,7 @@ bool CFrameTransport::RepublishFrameBuffer(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::CommitFrameBuffer(unsigned frameIndex,
|
void CLGMPFrameTransport::CommitFrameBuffer(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule, bool periodic,
|
const CFrameScheduler::Schedule& schedule, bool periodic,
|
||||||
bool deliveredToOwner)
|
bool deliveredToOwner)
|
||||||
{
|
{
|
||||||
@@ -1133,7 +1152,7 @@ void CFrameTransport::CommitFrameBuffer(unsigned frameIndex,
|
|||||||
m_frameScheduler.FrameRetained(schedule, now, periodic);
|
m_frameScheduler.FrameRetained(schedule, now, periodic);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::TryFrameSubmitted(unsigned frameIndex,
|
bool CLGMPFrameTransport::TryFrameSubmitted(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule)
|
const CFrameScheduler::Schedule& schedule)
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
||||||
@@ -1143,17 +1162,17 @@ bool CFrameTransport::TryFrameSubmitted(unsigned frameIndex,
|
|||||||
schedule, m_frame[frameIndex]->frameSerial);
|
schedule, m_frame[frameIndex]->frameSerial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::ObserveFrame(uint64_t now)
|
void CLGMPFrameTransport::ObserveFrame(uint64_t now)
|
||||||
{
|
{
|
||||||
m_frameScheduler.ObserveFrame(now);
|
m_frameScheduler.ObserveFrame(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::ForceFrame()
|
void CLGMPFrameTransport::ForceFrame()
|
||||||
{
|
{
|
||||||
m_frameScheduler.ForceFrame();
|
m_frameScheduler.ForceFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameTransport::GetPublishTarget(uint64_t now,
|
bool CLGMPFrameTransport::GetPublishTarget(uint64_t now,
|
||||||
uint64_t& target, CFrameScheduler::Schedule& schedule, bool& periodic,
|
uint64_t& target, CFrameScheduler::Schedule& schedule, bool& periodic,
|
||||||
bool& republish)
|
bool& republish)
|
||||||
{
|
{
|
||||||
@@ -1161,23 +1180,23 @@ bool CFrameTransport::GetPublishTarget(uint64_t now,
|
|||||||
now, target, schedule, periodic, republish);
|
now, target, schedule, periodic, republish);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::FrameMissed(
|
void CLGMPFrameTransport::FrameMissed(
|
||||||
const CFrameScheduler::Schedule& schedule, uint64_t now, bool periodic)
|
const CFrameScheduler::Schedule& schedule, uint64_t now, bool periodic)
|
||||||
{
|
{
|
||||||
m_frameScheduler.FrameMissed(schedule, now, periodic);
|
m_frameScheduler.FrameMissed(schedule, now, periodic);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::FrameSuperseded()
|
void CLGMPFrameTransport::FrameSuperseded()
|
||||||
{
|
{
|
||||||
m_frameScheduler.FrameSuperseded();
|
m_frameScheduler.FrameSuperseded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::TryRecordFrameTiming(uint64_t duration)
|
void CLGMPFrameTransport::TryRecordFrameTiming(uint64_t duration)
|
||||||
{
|
{
|
||||||
m_frameScheduler.TryRecordFrameTiming(duration);
|
m_frameScheduler.TryRecordFrameTiming(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::AbortFrameBuffer(unsigned frameIndex)
|
void CLGMPFrameTransport::AbortFrameBuffer(unsigned frameIndex)
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
||||||
return;
|
return;
|
||||||
@@ -1193,7 +1212,7 @@ void CFrameTransport::AbortFrameBuffer(unsigned frameIndex)
|
|||||||
ReleaseSRWLockExclusive(&m_framePublishLock);
|
ReleaseSRWLockExclusive(&m_framePublishLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::FailFrameBuffer(unsigned frameIndex)
|
void CLGMPFrameTransport::FailFrameBuffer(unsigned frameIndex)
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
||||||
return;
|
return;
|
||||||
@@ -1204,7 +1223,7 @@ void CFrameTransport::FailFrameBuffer(unsigned frameIndex)
|
|||||||
CompleteFrameBuffer(frameIndex, false);
|
CompleteFrameBuffer(frameIndex, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::CompleteFrameBuffer(
|
void CLGMPFrameTransport::CompleteFrameBuffer(
|
||||||
unsigned frameIndex, bool succeeded)
|
unsigned frameIndex, bool succeeded)
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
||||||
@@ -1232,7 +1251,7 @@ void CFrameTransport::CompleteFrameBuffer(
|
|||||||
ReleaseSRWLockExclusive(&m_framePublishLock);
|
ReleaseSRWLockExclusive(&m_framePublishLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::SetFrameTiming(unsigned frameIndex,
|
void CLGMPFrameTransport::SetFrameTiming(unsigned frameIndex,
|
||||||
uint64_t captureTime, uint64_t postProcessTime, uint64_t copyTime,
|
uint64_t captureTime, uint64_t postProcessTime, uint64_t copyTime,
|
||||||
uint64_t readyTime, uint64_t holdTime,
|
uint64_t readyTime, uint64_t holdTime,
|
||||||
const CFrameScheduler::Schedule& schedule, uint64_t completedAt)
|
const CFrameScheduler::Schedule& schedule, uint64_t completedAt)
|
||||||
@@ -1257,10 +1276,10 @@ void CFrameTransport::SetFrameTiming(unsigned frameIndex,
|
|||||||
InterlockedExchange((volatile LONG *)&frame->timingValid, 1);
|
InterlockedExchange((volatile LONG *)&frame->timingValid, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::WriteFrameBuffer(unsigned frameIndex, void * src,
|
void CLGMPFrameTransport::WriteFrameBuffer(unsigned frameIndex, void * src,
|
||||||
size_t offset, size_t len, bool setWritePos) const
|
size_t offset, size_t len, bool setWritePos) const
|
||||||
{
|
{
|
||||||
FrameBuffer * fb = m_frameBuffer[frameIndex];
|
LGMPBuffer * fb = m_frameBuffer[frameIndex];
|
||||||
|
|
||||||
memcpy(
|
memcpy(
|
||||||
reinterpret_cast<void *>(
|
reinterpret_cast<void *>(
|
||||||
@@ -1273,11 +1292,11 @@ void CFrameTransport::WriteFrameBuffer(unsigned frameIndex, void * src,
|
|||||||
fb->wp = (uint32_t)(offset + len);
|
fb->wp = (uint32_t)(offset + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::WriteFrameBufferRows(unsigned frameIndex,
|
void CLGMPFrameTransport::WriteFrameBufferRows(unsigned frameIndex,
|
||||||
void * src, size_t offset, size_t rowBytes, size_t pitch,
|
void * src, size_t offset, size_t rowBytes, size_t pitch,
|
||||||
unsigned rows) const
|
unsigned rows) const
|
||||||
{
|
{
|
||||||
FrameBuffer * fb = m_frameBuffer[frameIndex];
|
LGMPBuffer * fb = m_frameBuffer[frameIndex];
|
||||||
uint8_t * dst = fb->data + offset;
|
uint8_t * dst = fb->data + offset;
|
||||||
uint8_t * source = static_cast<uint8_t *>(src) + offset;
|
uint8_t * source = static_cast<uint8_t *>(src) + offset;
|
||||||
for (unsigned row = 0; row < rows; ++row)
|
for (unsigned row = 0; row < rows; ++row)
|
||||||
@@ -1288,9 +1307,9 @@ void CFrameTransport::WriteFrameBufferRows(unsigned frameIndex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrameTransport::FinalizeFrameBuffer(unsigned frameIndex) const
|
void CLGMPFrameTransport::FinalizeFrameBuffer(unsigned frameIndex) const
|
||||||
{
|
{
|
||||||
const KVMFRFrame * frame = m_frame[frameIndex];
|
const KVMFRFrame * frame = m_frame[frameIndex];
|
||||||
FrameBuffer * fb = m_frameBuffer[frameIndex];
|
LGMPBuffer * fb = m_frameBuffer[frameIndex];
|
||||||
fb->wp = frame->dataHeight * frame->pitch;
|
fb->wp = frame->dataHeight * frame->pitch;
|
||||||
}
|
}
|
||||||
@@ -28,18 +28,21 @@ extern "C" {
|
|||||||
#include "lgmp/host.h"
|
#include "lgmp/host.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "capture/CFrameScheduler.h"
|
|
||||||
#include "capture/FrameBufferTypes.h"
|
|
||||||
#include "common/KVMFR.h"
|
#include "common/KVMFR.h"
|
||||||
#include "postprocess/D12FrameFormat.h"
|
#include "transport/CFrameScheduler.h"
|
||||||
#include "transport/FrameMemoryLimits.h"
|
#include "transport/FrameMemoryLimits.h"
|
||||||
|
#include "transport/IFrameTransport.h"
|
||||||
|
|
||||||
class CIVSHMEM;
|
class CIVSHMEM;
|
||||||
class CLGMPHost;
|
class CLGMPHost;
|
||||||
|
class CLGMPTransport;
|
||||||
|
struct LGMPBuffer;
|
||||||
|
|
||||||
class CFrameTransport
|
class CLGMPFrameTransport final : public IFrameTransport
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
|
friend class CLGMPTransport;
|
||||||
|
|
||||||
struct SubscriberSnapshot
|
struct SubscriberSnapshot
|
||||||
{
|
{
|
||||||
uint32_t clientIDs [LGMP_MAX_CLIENTS] = {};
|
uint32_t clientIDs [LGMP_MAX_CLIENTS] = {};
|
||||||
@@ -103,7 +106,7 @@ private:
|
|||||||
uint32_t m_frameSerial = 0;
|
uint32_t m_frameSerial = 0;
|
||||||
PLGMPMemory m_frameMemory[LGMP_Q_FRAME_BUFFER_LEN] = {};
|
PLGMPMemory m_frameMemory[LGMP_Q_FRAME_BUFFER_LEN] = {};
|
||||||
KVMFRFrame * m_frame [LGMP_Q_FRAME_BUFFER_LEN] = {};
|
KVMFRFrame * m_frame [LGMP_Q_FRAME_BUFFER_LEN] = {};
|
||||||
FrameBuffer * m_frameBuffer[LGMP_Q_FRAME_BUFFER_LEN] = {};
|
LGMPBuffer * m_frameBuffer[LGMP_Q_FRAME_BUFFER_LEN] = {};
|
||||||
|
|
||||||
unsigned m_width = 0;
|
unsigned m_width = 0;
|
||||||
unsigned m_height = 0;
|
unsigned m_height = 0;
|
||||||
@@ -136,74 +139,77 @@ private:
|
|||||||
uint32_t excludeClientID, uint64_t now);
|
uint32_t excludeClientID, uint64_t now);
|
||||||
bool PostSharedOwnerFrame(unsigned frameIndex,
|
bool PostSharedOwnerFrame(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule);
|
const CFrameScheduler::Schedule& schedule);
|
||||||
|
CLGMPFrameTransport(CLGMPHost& host, CIVSHMEM& ivshmem);
|
||||||
public:
|
|
||||||
CFrameTransport(CLGMPHost& host, CIVSHMEM& ivshmem);
|
|
||||||
~CFrameTransport();
|
|
||||||
|
|
||||||
CFrameTransport(const CFrameTransport&) = delete;
|
|
||||||
CFrameTransport& operator=(const CFrameTransport&) = delete;
|
|
||||||
|
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
void SealMemoryLayout();
|
void SealMemoryLayout();
|
||||||
bool Setup(size_t alignSize);
|
bool Setup(size_t alignSize);
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
FrameMemoryLimits GetMemoryLimits() const;
|
FrameMemoryLimits GetMemoryLimits() const;
|
||||||
size_t GetMaxFrameSize() const { return m_maxFrameSize; }
|
|
||||||
CIVSHMEM& GetIVSHMEM() { return m_ivshmem; }
|
|
||||||
|
|
||||||
SubscriberSnapshot SnapshotSubscribers() const;
|
SubscriberSnapshot SnapshotSubscribers() const;
|
||||||
void FinalizeSubscribers(
|
void FinalizeSubscribers(
|
||||||
const SubscriberSnapshot& snapshot, uint64_t now);
|
const SubscriberSnapshot& snapshot, uint64_t now);
|
||||||
bool UpdateSchedule(uint32_t sourceClientID,
|
bool UpdateSchedule(uint32_t sourceClientID,
|
||||||
const KVMFRFrameSchedule& schedule, uint64_t now);
|
const FrameScheduleUpdate& schedule, uint64_t now);
|
||||||
|
|
||||||
|
public:
|
||||||
|
~CLGMPFrameTransport() override;
|
||||||
|
|
||||||
|
CLGMPFrameTransport(const CLGMPFrameTransport&) = delete;
|
||||||
|
CLGMPFrameTransport& operator=(const CLGMPFrameTransport&) = delete;
|
||||||
|
|
||||||
|
size_t GetMaxFrameSize() const override { return m_maxFrameSize; }
|
||||||
|
|
||||||
bool FrameBufferAvailable(const CFrameScheduler::Schedule& schedule,
|
bool FrameBufferAvailable(const CFrameScheduler::Schedule& schedule,
|
||||||
bool allowReadyReplacement = true);
|
bool allowReadyReplacement = true) override;
|
||||||
bool HasPublishedFrame() const
|
bool HasPublishedFrame() const override
|
||||||
{
|
{
|
||||||
return m_readyFrameIndex.load(std::memory_order_acquire) >= 0;
|
return m_readyFrameIndex.load(std::memory_order_acquire) >= 0;
|
||||||
}
|
}
|
||||||
void ProcessFrameQueue();
|
void ProcessDeliveries() override;
|
||||||
bool GetSharedFrameTarget(uint64_t now, uint64_t& target);
|
bool GetPendingDeliveryTarget(
|
||||||
bool ReplaySharedFrame(uint64_t now, bool& retry);
|
uint64_t now, uint64_t& target) override;
|
||||||
|
bool RetryPendingDelivery(uint64_t now, bool& retry) override;
|
||||||
PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch,
|
PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch,
|
||||||
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
|
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
|
||||||
const RECT * dirtyRects, unsigned nbDirtyRects,
|
const RECT * dirtyRects, unsigned nbDirtyRects,
|
||||||
const CFrameScheduler::Schedule& schedule,
|
const CFrameScheduler::Schedule& schedule,
|
||||||
bool allowReadyReplacement = true);
|
bool allowReadyReplacement = true) override;
|
||||||
bool PublishFrameBuffer(unsigned frameIndex,
|
bool PublishFrameBuffer(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule, bool& deliveredToOwner);
|
const CFrameScheduler::Schedule& schedule,
|
||||||
bool RepublishFrameBuffer(const CFrameScheduler::Schedule& schedule);
|
bool& deliveredToOwner) override;
|
||||||
|
bool RepublishFrameBuffer(
|
||||||
|
const CFrameScheduler::Schedule& schedule) override;
|
||||||
bool TryFrameSubmitted(unsigned frameIndex,
|
bool TryFrameSubmitted(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule);
|
const CFrameScheduler::Schedule& schedule) override;
|
||||||
void CommitFrameBuffer(unsigned frameIndex,
|
void CommitFrameBuffer(unsigned frameIndex,
|
||||||
const CFrameScheduler::Schedule& schedule, bool periodic,
|
const CFrameScheduler::Schedule& schedule, bool periodic,
|
||||||
bool deliveredToOwner);
|
bool deliveredToOwner) override;
|
||||||
void AbortFrameBuffer(unsigned frameIndex);
|
void AbortFrameBuffer(unsigned frameIndex) override;
|
||||||
void FailFrameBuffer(unsigned frameIndex);
|
void FailFrameBuffer(unsigned frameIndex) override;
|
||||||
void CompleteFrameBuffer(unsigned frameIndex, bool succeeded);
|
void CompleteFrameBuffer(
|
||||||
|
unsigned frameIndex, bool succeeded) override;
|
||||||
void SetFrameTiming(unsigned frameIndex, uint64_t captureTime,
|
void SetFrameTiming(unsigned frameIndex, uint64_t captureTime,
|
||||||
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
|
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
|
||||||
uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
|
uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
|
||||||
uint64_t completedAt);
|
uint64_t completedAt) override;
|
||||||
void WriteFrameBuffer(unsigned frameIndex, void * src, size_t offset,
|
void WriteFrameBuffer(unsigned frameIndex, void * src, size_t offset,
|
||||||
size_t len, bool setWritePos) const;
|
size_t len, bool setWritePos) const override;
|
||||||
void WriteFrameBufferRows(unsigned frameIndex, void * src,
|
void WriteFrameBufferRows(unsigned frameIndex, void * src,
|
||||||
size_t offset, size_t rowBytes, size_t pitch, unsigned rows) const;
|
size_t offset, size_t rowBytes, size_t pitch,
|
||||||
void FinalizeFrameBuffer(unsigned frameIndex) const;
|
unsigned rows) const override;
|
||||||
|
void FinalizeFrameBuffer(unsigned frameIndex) const override;
|
||||||
|
|
||||||
void ObserveFrame(uint64_t now);
|
void ObserveFrame(uint64_t now) override;
|
||||||
void ForceFrame();
|
void ForceFrame() override;
|
||||||
bool GetPublishTarget(uint64_t now, uint64_t& target,
|
bool GetPublishTarget(uint64_t now, uint64_t& target,
|
||||||
CFrameScheduler::Schedule& schedule, bool& periodic, bool& republish);
|
CFrameScheduler::Schedule& schedule, bool& periodic,
|
||||||
|
bool& republish) override;
|
||||||
void FrameMissed(const CFrameScheduler::Schedule& schedule,
|
void FrameMissed(const CFrameScheduler::Schedule& schedule,
|
||||||
uint64_t now, bool periodic);
|
uint64_t now, bool periodic) override;
|
||||||
void FrameSuperseded();
|
void FrameSuperseded() override;
|
||||||
HANDLE GetFrameScheduleEvent() const
|
HANDLE GetFrameScheduleEvent() const override
|
||||||
{
|
{
|
||||||
return m_frameScheduler.GetWakeEvent();
|
return m_frameScheduler.GetWakeEvent();
|
||||||
}
|
}
|
||||||
void TryRecordFrameTiming(uint64_t duration);
|
void TryRecordFrameTiming(uint64_t duration) override;
|
||||||
};
|
};
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "transport/CLGMPHost.h"
|
#include "transport/lgmp/CLGMPHost.h"
|
||||||
|
|
||||||
#include "transport/CIVSHMEM.h"
|
#include "transport/lgmp/CIVSHMEM.h"
|
||||||
#include "platform/CPlatformInfo.h"
|
#include "platform/CPlatformInfo.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
#include "VersionInfo.h"
|
#include "VersionInfo.h"
|
||||||
183
idd/LGIdd/transport/lgmp/CLGMPTransport.cpp
Normal file
183
idd/LGIdd/transport/lgmp/CLGMPTransport.cpp
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "transport/lgmp/CLGMPTransport.h"
|
||||||
|
|
||||||
|
#include "CDebug.h"
|
||||||
|
#include "common/KVMFR.h"
|
||||||
|
|
||||||
|
static bool TranslateFrameScheduleFlags(
|
||||||
|
uint32_t source, uint32_t& destination)
|
||||||
|
{
|
||||||
|
static const uint32_t validFlags =
|
||||||
|
KVMFR_FRAME_SCHEDULE_ACTIVE |
|
||||||
|
KVMFR_FRAME_SCHEDULE_RELEASE |
|
||||||
|
KVMFR_FRAME_SCHEDULE_RESET |
|
||||||
|
KVMFR_FRAME_SCHEDULE_IMMEDIATE;
|
||||||
|
|
||||||
|
if (source & ~validFlags)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
destination = 0;
|
||||||
|
if (source & KVMFR_FRAME_SCHEDULE_ACTIVE)
|
||||||
|
destination |= FRAME_SCHEDULE_ACTIVE;
|
||||||
|
if (source & KVMFR_FRAME_SCHEDULE_RELEASE)
|
||||||
|
destination |= FRAME_SCHEDULE_RELEASE;
|
||||||
|
if (source & KVMFR_FRAME_SCHEDULE_RESET)
|
||||||
|
destination |= FRAME_SCHEDULE_RESET;
|
||||||
|
if (source & KVMFR_FRAME_SCHEDULE_IMMEDIATE)
|
||||||
|
destination |= FRAME_SCHEDULE_IMMEDIATE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLGMPTransport::CLGMPTransport() :
|
||||||
|
m_control(m_host),
|
||||||
|
m_frames(m_host, m_ivshmem)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ITransport::OpenResult CLGMPTransport::Open()
|
||||||
|
{
|
||||||
|
if (m_ivshmem.GetMem())
|
||||||
|
return OpenResult::SUCCESS;
|
||||||
|
|
||||||
|
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
||||||
|
return OpenResult::RETRY;
|
||||||
|
|
||||||
|
return OpenResult::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLGMPTransport::Initialize()
|
||||||
|
{
|
||||||
|
if (!m_host.Initialize(m_ivshmem))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Preserve the shared-memory layout: frame queues precede the pointer queue
|
||||||
|
// and its retained cursor and color-transform allocations.
|
||||||
|
if (!m_frames.Initialize() || !m_control.Initialize())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_frames.SealMemoryLayout();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLGMPTransport::Setup(size_t alignment)
|
||||||
|
{
|
||||||
|
return m_frames.Setup(alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLGMPTransport::Process(ITransportEvents& events)
|
||||||
|
{
|
||||||
|
const LGMP_STATUS processStatus = m_host.Process();
|
||||||
|
if (processStatus != LGMP_OK)
|
||||||
|
{
|
||||||
|
if (processStatus == LGMP_ERR_CORRUPTED)
|
||||||
|
{
|
||||||
|
DEBUG_WARN(
|
||||||
|
"LGMP reported the shared memory has been corrupted, attempting to recover\n");
|
||||||
|
// TODO: reinitialize LGMP.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_ERROR("lgmpHostProcess Failed: %s",
|
||||||
|
lgmpStatusString(processStatus));
|
||||||
|
// TODO: shut down LGMP.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_t now = CFrameScheduler::Nanotime();
|
||||||
|
|
||||||
|
// Take the frame subscriber snapshot before processing scheduling messages,
|
||||||
|
// then publish both updates together just as the original timer did.
|
||||||
|
const CLGMPFrameTransport::SubscriberSnapshot subscribers =
|
||||||
|
m_frames.SnapshotSubscribers();
|
||||||
|
|
||||||
|
uint8_t data[LGMP_MSGS_SIZE];
|
||||||
|
size_t size;
|
||||||
|
uint32_t sourceClientID;
|
||||||
|
LGMP_STATUS status;
|
||||||
|
while ((status = m_control.ReadDataWithSource(
|
||||||
|
data, &size, &sourceClientID)) == LGMP_OK)
|
||||||
|
{
|
||||||
|
KVMFRMessage * msg = reinterpret_cast<KVMFRMessage *>(data);
|
||||||
|
switch (msg->type)
|
||||||
|
{
|
||||||
|
case KVMFR_MESSAGE_SETCURSORPOS:
|
||||||
|
{
|
||||||
|
KVMFRSetCursorPos * position =
|
||||||
|
reinterpret_cast<KVMFRSetCursorPos *>(msg);
|
||||||
|
events.OnSetCursorPos(position->x, position->y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case KVMFR_MESSAGE_WINDOWSIZE:
|
||||||
|
{
|
||||||
|
KVMFRWindowSize * window =
|
||||||
|
reinterpret_cast<KVMFRWindowSize *>(msg);
|
||||||
|
events.OnSetResolution(window->w, window->h);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case KVMFR_MESSAGE_FRAME_SCHEDULE:
|
||||||
|
{
|
||||||
|
const KVMFRFrameSchedule * schedule =
|
||||||
|
reinterpret_cast<KVMFRFrameSchedule *>(msg);
|
||||||
|
uint32_t translatedFlags = 0;
|
||||||
|
bool valid = size == sizeof(*schedule) &&
|
||||||
|
TranslateFrameScheduleFlags(schedule->flags, translatedFlags);
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
FrameScheduleUpdate update = {};
|
||||||
|
update.clientID = schedule->clientID;
|
||||||
|
update.generation = schedule->generation;
|
||||||
|
update.flags = translatedFlags;
|
||||||
|
update.period = schedule->period;
|
||||||
|
update.targetSlack = schedule->targetSlack;
|
||||||
|
update.phaseError = schedule->phaseError;
|
||||||
|
update.feedbackFrameSerial = schedule->feedbackFrameSerial;
|
||||||
|
update.feedbackScheduleEpoch = schedule->feedbackScheduleEpoch;
|
||||||
|
update.feedbackDeadlineSerial = schedule->feedbackDeadlineSerial;
|
||||||
|
update.lease = schedule->lease;
|
||||||
|
valid = m_frames.UpdateSchedule(sourceClientID, update, now);
|
||||||
|
}
|
||||||
|
if (!valid)
|
||||||
|
DEBUG_WARN("Ignoring invalid KVMFR frame schedule");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_control.AckData();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_frames.FinalizeSubscribers(subscribers, now);
|
||||||
|
|
||||||
|
if (m_control.HasNewSubscribers())
|
||||||
|
m_control.ResendState();
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameMemoryLimits CLGMPTransport::GetMemoryLimits() const
|
||||||
|
{
|
||||||
|
return m_frames.GetMemoryLimits();
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectFrameBufferMemory CLGMPTransport::GetDirectMemory() const
|
||||||
|
{
|
||||||
|
return {m_ivshmem.GetMem(), m_ivshmem.GetSize()};
|
||||||
|
}
|
||||||
56
idd/LGIdd/transport/lgmp/CLGMPTransport.h
Normal file
56
idd/LGIdd/transport/lgmp/CLGMPTransport.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "transport/ITransport.h"
|
||||||
|
#include "transport/lgmp/CIVSHMEM.h"
|
||||||
|
#include "transport/lgmp/CLGMPControl.h"
|
||||||
|
#include "transport/lgmp/CLGMPFrameTransport.h"
|
||||||
|
#include "transport/lgmp/CLGMPHost.h"
|
||||||
|
|
||||||
|
class CLGMPTransport final : public ITransport
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Keep this declaration order. Destruction must release frame and control
|
||||||
|
// allocations before the LGMP host and its IVSHMEM mapping are destroyed.
|
||||||
|
CIVSHMEM m_ivshmem;
|
||||||
|
CLGMPHost m_host;
|
||||||
|
CLGMPControl m_control;
|
||||||
|
CLGMPFrameTransport m_frames;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CLGMPTransport();
|
||||||
|
~CLGMPTransport() override = default;
|
||||||
|
|
||||||
|
CLGMPTransport(const CLGMPTransport&) = delete;
|
||||||
|
CLGMPTransport& operator=(const CLGMPTransport&) = delete;
|
||||||
|
|
||||||
|
OpenResult Open() override;
|
||||||
|
bool Initialize() override;
|
||||||
|
bool Setup(size_t alignment) override;
|
||||||
|
void Process(ITransportEvents& events) override;
|
||||||
|
|
||||||
|
FrameMemoryLimits GetMemoryLimits() const override;
|
||||||
|
DirectFrameBufferMemory GetDirectMemory() const override;
|
||||||
|
|
||||||
|
IFrameTransport& Frames() override { return m_frames; }
|
||||||
|
IControlTransport& Control() override { return m_control; }
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user