mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 13:37:22 +00:00
[idd] implemented frame feed from the guest (very hacky)
This is NOT READY for general consumption, if you decide to make use of this driver, DO NOT ASK FOR SUPPORT.
This commit is contained in:
parent
3c85957b99
commit
0c3dce3ca6
@ -4,6 +4,8 @@
|
|||||||
#include "CPlatformInfo.h"
|
#include "CPlatformInfo.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
static const struct LGMPQueueConfig FRAME_QUEUE_CONFIG =
|
static const struct LGMPQueueConfig FRAME_QUEUE_CONFIG =
|
||||||
{
|
{
|
||||||
LGMP_Q_FRAME, //queueID
|
LGMP_Q_FRAME, //queueID
|
||||||
@ -73,7 +75,10 @@ void CIndirectDeviceContext::InitAdapter()
|
|||||||
IDARG_OUT_ADAPTER_INIT initOut;
|
IDARG_OUT_ADAPTER_INIT initOut;
|
||||||
NTSTATUS status = IddCxAdapterInitAsync(&init, &initOut);
|
NTSTATUS status = IddCxAdapterInitAsync(&init, &initOut);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DBGPRINT("IddCxAdapterInitAsync Failed");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_adapter = initOut.AdapterObject;
|
m_adapter = initOut.AdapterObject;
|
||||||
|
|
||||||
@ -147,17 +152,18 @@ void CIndirectDeviceContext::FinishInit(UINT connectorIndex)
|
|||||||
IDARG_OUT_MONITORCREATE createOut;
|
IDARG_OUT_MONITORCREATE createOut;
|
||||||
NTSTATUS status = IddCxMonitorCreate(m_adapter, &create, &createOut);
|
NTSTATUS status = IddCxMonitorCreate(m_adapter, &create, &createOut);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
DBGPRINT("IddCxMonitorCreate Failed");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(createOut.MonitorObject);
|
auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(createOut.MonitorObject);
|
||||||
wrapper->context = new CIndirectMonitorContext(createOut.MonitorObject);
|
wrapper->context = new CIndirectMonitorContext(createOut.MonitorObject, this);
|
||||||
|
|
||||||
IDARG_OUT_MONITORARRIVAL out;
|
IDARG_OUT_MONITORARRIVAL out;
|
||||||
status = IddCxMonitorArrival(createOut.MonitorObject, &out);
|
status = IddCxMonitorArrival(createOut.MonitorObject, &out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
bool CIndirectDeviceContext::SetupLGMP()
|
bool CIndirectDeviceContext::SetupLGMP()
|
||||||
{
|
{
|
||||||
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
||||||
@ -177,6 +183,11 @@ bool CIndirectDeviceContext::SetupLGMP()
|
|||||||
const std::string & model = CPlatformInfo::GetCPUModel();
|
const std::string & model = CPlatformInfo::GetCPUModel();
|
||||||
|
|
||||||
KVMFRRecord_VMInfo * vmInfo = static_cast<KVMFRRecord_VMInfo *>(calloc(1, sizeof(*vmInfo)));
|
KVMFRRecord_VMInfo * vmInfo = static_cast<KVMFRRecord_VMInfo *>(calloc(1, sizeof(*vmInfo)));
|
||||||
|
if (!vmInfo)
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to allocate KVMFRRecord_VMInfo");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
vmInfo->cpus = static_cast<uint8_t>(CPlatformInfo::GetProcCount ());
|
vmInfo->cpus = static_cast<uint8_t>(CPlatformInfo::GetProcCount ());
|
||||||
vmInfo->cores = static_cast<uint8_t>(CPlatformInfo::GetCoreCount ());
|
vmInfo->cores = static_cast<uint8_t>(CPlatformInfo::GetCoreCount ());
|
||||||
vmInfo->sockets = static_cast<uint8_t>(CPlatformInfo::GetSocketCount());
|
vmInfo->sockets = static_cast<uint8_t>(CPlatformInfo::GetSocketCount());
|
||||||
@ -186,6 +197,12 @@ bool CIndirectDeviceContext::SetupLGMP()
|
|||||||
strncpy_s(vmInfo->capture, "Idd Driver", sizeof(vmInfo->capture));
|
strncpy_s(vmInfo->capture, "Idd Driver", sizeof(vmInfo->capture));
|
||||||
|
|
||||||
KVMFRRecord * record = static_cast<KVMFRRecord *>(calloc(1, sizeof(*record)));
|
KVMFRRecord * record = static_cast<KVMFRRecord *>(calloc(1, sizeof(*record)));
|
||||||
|
if (!record)
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to allocate KVMFRRecord");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
record->type = KVMFR_RECORD_VMINFO;
|
record->type = KVMFR_RECORD_VMINFO;
|
||||||
record->size = sizeof(*vmInfo) + (uint32_t)model.length() + 1;
|
record->size = sizeof(*vmInfo) + (uint32_t)model.length() + 1;
|
||||||
|
|
||||||
@ -196,11 +213,23 @@ bool CIndirectDeviceContext::SetupLGMP()
|
|||||||
|
|
||||||
{
|
{
|
||||||
KVMFRRecord_OSInfo * osInfo = static_cast<KVMFRRecord_OSInfo *>(calloc(1, sizeof(*osInfo)));
|
KVMFRRecord_OSInfo * osInfo = static_cast<KVMFRRecord_OSInfo *>(calloc(1, sizeof(*osInfo)));
|
||||||
|
if (!osInfo)
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to allocate KVMFRRecord_OSInfo");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
osInfo->os = KVMFR_OS_WINDOWS;
|
osInfo->os = KVMFR_OS_WINDOWS;
|
||||||
|
|
||||||
const std::string & osName = CPlatformInfo::GetProductName();
|
const std::string & osName = CPlatformInfo::GetProductName();
|
||||||
|
|
||||||
KVMFRRecord* record = static_cast<KVMFRRecord*>(calloc(1, sizeof(*record)));
|
KVMFRRecord* record = static_cast<KVMFRRecord*>(calloc(1, sizeof(*record)));
|
||||||
|
if (!record)
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to allocate KVMFRRecord");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
record->type = KVMFR_RECORD_OSINFO;
|
record->type = KVMFR_RECORD_OSINFO;
|
||||||
record->size = sizeof(*osInfo) + (uint32_t)osName.length() + 1;
|
record->size = sizeof(*osInfo) + (uint32_t)osName.length() + 1;
|
||||||
|
|
||||||
@ -330,3 +359,72 @@ void CIndirectDeviceContext::LGMPTimer()
|
|||||||
lgmpHostAckData(m_pointerQueue);
|
lgmpHostAckData(m_pointerQueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FORMAT format, void* data)
|
||||||
|
{
|
||||||
|
if (!m_lgmp || !m_frameQueue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_width != width || m_height != height || m_format != format)
|
||||||
|
{
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
m_format = format;
|
||||||
|
++m_formatVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lgmpHostQueuePending(m_frameQueue) == LGMP_Q_FRAME_LEN)
|
||||||
|
Sleep(0);
|
||||||
|
|
||||||
|
if (++m_frameIndex == LGMP_Q_FRAME_LEN)
|
||||||
|
m_frameIndex = 0;
|
||||||
|
|
||||||
|
KVMFRFrame * fi = (KVMFRFrame *)lgmpHostMemPtr(m_frameMemory[m_frameIndex]);
|
||||||
|
int bpp = 4;
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM : fi->type = FRAME_TYPE_BGRA ; break;
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM : fi->type = FRAME_TYPE_RGBA ; break;
|
||||||
|
case DXGI_FORMAT_R10G10B10A2_UNORM : fi->type = FRAME_TYPE_RGBA10 ; break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||||
|
fi->type = FRAME_TYPE_RGBA16F;
|
||||||
|
bpp = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DBGPRINT("Unsuppoted DXGI format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: this should not really be done here, this is a hack
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4200)
|
||||||
|
struct FrameBuffer
|
||||||
|
{
|
||||||
|
volatile uint32_t wp;
|
||||||
|
uint8_t data[0];
|
||||||
|
};
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
fi->formatVer = m_formatVer;
|
||||||
|
fi->frameSerial = m_frameSerial++;
|
||||||
|
fi->screenWidth = width;
|
||||||
|
fi->screenHeight = height;
|
||||||
|
fi->frameWidth = width;
|
||||||
|
fi->frameHeight = height;
|
||||||
|
fi->stride = width * bpp;
|
||||||
|
fi->pitch = pitch;
|
||||||
|
fi->offset = (uint32_t)(CPlatformInfo::GetPageSize() - sizeof(FrameBuffer));
|
||||||
|
fi->flags = 0;
|
||||||
|
fi->rotation = FRAME_ROT_0;
|
||||||
|
|
||||||
|
fi->damageRectsCount = 0;
|
||||||
|
|
||||||
|
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)fi) + fi->offset);
|
||||||
|
fb->wp = 0;
|
||||||
|
|
||||||
|
lgmpHostQueuePost(m_frameQueue, 0, m_frameMemory[m_frameIndex]);
|
||||||
|
memcpy(fb->data, data, (size_t)height * (size_t)pitch);
|
||||||
|
fb->wp = height * pitch;
|
||||||
|
}
|
@ -29,8 +29,15 @@ private:
|
|||||||
PLGMPMemory m_pointerShapeMemory[POINTER_SHAPE_BUFFERS] = {};
|
PLGMPMemory m_pointerShapeMemory[POINTER_SHAPE_BUFFERS] = {};
|
||||||
|
|
||||||
size_t m_maxFrameSize = 0;
|
size_t m_maxFrameSize = 0;
|
||||||
|
int m_frameIndex = 0;
|
||||||
|
uint32_t m_formatVer = 0;
|
||||||
|
uint32_t m_frameSerial = 0;
|
||||||
PLGMPMemory m_frameMemory[LGMP_Q_FRAME_LEN] = {};
|
PLGMPMemory m_frameMemory[LGMP_Q_FRAME_LEN] = {};
|
||||||
|
|
||||||
|
int m_width = 0;
|
||||||
|
int m_height = 0;
|
||||||
|
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
|
||||||
bool SetupLGMP();
|
bool SetupLGMP();
|
||||||
|
|
||||||
void LGMPTimer();
|
void LGMPTimer();
|
||||||
@ -46,6 +53,8 @@ public:
|
|||||||
void InitAdapter();
|
void InitAdapter();
|
||||||
|
|
||||||
void FinishInit(UINT connectorIndex);
|
void FinishInit(UINT connectorIndex);
|
||||||
|
|
||||||
|
void SendFrame(int width, int height, int pitch, DXGI_FORMAT format, void* data);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CIndirectDeviceContextWrapper
|
struct CIndirectDeviceContextWrapper
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "CIndirectMonitorContext.h"
|
#include "CIndirectMonitorContext.h"
|
||||||
#include "Direct3DDevice.h"
|
#include "Direct3DDevice.h"
|
||||||
|
|
||||||
CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor) :
|
CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device) :
|
||||||
m_monitor(monitor)
|
m_monitor(monitor),
|
||||||
|
m_devContext(device)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID re
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_thread.reset(new CSwapChainProcessor(swapChain, device, newFrameEvent));
|
m_thread.reset(new CSwapChainProcessor(m_devContext, swapChain, device, newFrameEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIndirectMonitorContext::UnassignSwapChain()
|
void CIndirectMonitorContext::UnassignSwapChain()
|
||||||
|
@ -5,16 +5,18 @@
|
|||||||
#include <IddCx.h>
|
#include <IddCx.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "CIndirectDeviceContext.h"
|
||||||
#include "CSwapChainProcessor.h"
|
#include "CSwapChainProcessor.h"
|
||||||
|
|
||||||
class CIndirectMonitorContext
|
class CIndirectMonitorContext
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
IDDCX_MONITOR m_monitor;
|
IDDCX_MONITOR m_monitor;
|
||||||
|
CIndirectDeviceContext * m_devContext;
|
||||||
std::unique_ptr<CSwapChainProcessor> m_thread;
|
std::unique_ptr<CSwapChainProcessor> m_thread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor);
|
CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device);
|
||||||
|
|
||||||
virtual ~CIndirectMonitorContext();
|
virtual ~CIndirectMonitorContext();
|
||||||
|
|
||||||
|
@ -218,6 +218,11 @@ void CPlatformInfo::InitCPUInfo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BYTE * buffer = static_cast<BYTE *>(_malloca(cb));
|
BYTE * buffer = static_cast<BYTE *>(_malloca(cb));
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to allocate buffer for processor information");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!GetLogicalProcessorInformationEx(RelationAll,
|
if (!GetLogicalProcessorInformationEx(RelationAll,
|
||||||
(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)buffer, &cb))
|
(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)buffer, &cb))
|
||||||
{
|
{
|
||||||
|
@ -1,36 +1,48 @@
|
|||||||
#include "CSwapChainProcessor.h"
|
#include "CSwapChainProcessor.h"
|
||||||
|
|
||||||
#include <avrt.h>
|
#include <avrt.h>
|
||||||
|
#include "Debug.h"
|
||||||
|
|
||||||
|
#define LOCK_CONTEXT() \
|
||||||
|
while (InterlockedCompareExchange((volatile LONG*)&m_contextLock, 1, 0) != 0) {};
|
||||||
|
|
||||||
CSwapChainProcessor::CSwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent) :
|
#define UNLOCK_CONTEXT() \
|
||||||
|
InterlockedExchange((volatile LONG*)&m_contextLock, 0);
|
||||||
|
|
||||||
|
CSwapChainProcessor::CSwapChainProcessor(CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||||
|
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent) :
|
||||||
|
m_devContext(devContext),
|
||||||
m_hSwapChain(hSwapChain),
|
m_hSwapChain(hSwapChain),
|
||||||
m_device(device),
|
m_device(device),
|
||||||
m_newFrameEvent(newFrameEvent)
|
m_newFrameEvent(newFrameEvent)
|
||||||
{
|
{
|
||||||
m_terminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
m_terminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||||
m_thread.Attach(CreateThread(nullptr, 0, RunThread, this, 0, nullptr));
|
m_thread[0].Attach(CreateThread(nullptr, 0, _SwapChainThread, this, 0, nullptr));
|
||||||
|
m_thread[1].Attach(CreateThread(nullptr, 0, _FrameThread , this, 0, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSwapChainProcessor::~CSwapChainProcessor()
|
CSwapChainProcessor::~CSwapChainProcessor()
|
||||||
{
|
{
|
||||||
SetEvent(m_terminateEvent.Get());
|
SetEvent(m_terminateEvent.Get());
|
||||||
if (m_thread.Get())
|
if (m_thread[0].Get())
|
||||||
WaitForSingleObject(m_thread.Get(), INFINITE);
|
WaitForSingleObject(m_thread[0].Get(), INFINITE);
|
||||||
|
if (m_thread[1].Get())
|
||||||
|
WaitForSingleObject(m_thread[1].Get(), INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD CALLBACK CSwapChainProcessor::RunThread(LPVOID argument)
|
DWORD CALLBACK CSwapChainProcessor::_SwapChainThread(LPVOID arg)
|
||||||
{
|
{
|
||||||
reinterpret_cast<CSwapChainProcessor*>(argument)->Run();
|
reinterpret_cast<CSwapChainProcessor*>(arg)->SwapChainThread();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSwapChainProcessor::Run()
|
void CSwapChainProcessor::SwapChainThread()
|
||||||
{
|
{
|
||||||
DWORD avTask = 0;
|
DWORD avTask = 0;
|
||||||
HANDLE avTaskHandle = AvSetMmThreadCharacteristicsW(L"Distribution", &avTask);
|
HANDLE avTaskHandle = AvSetMmThreadCharacteristicsW(L"Distribution", &avTask);
|
||||||
|
|
||||||
RunCore();
|
DBGPRINT("Start");
|
||||||
|
SwapChainThreadCore();
|
||||||
|
|
||||||
WdfObjectDelete((WDFOBJECT)m_hSwapChain);
|
WdfObjectDelete((WDFOBJECT)m_hSwapChain);
|
||||||
m_hSwapChain = nullptr;
|
m_hSwapChain = nullptr;
|
||||||
@ -38,28 +50,41 @@ void CSwapChainProcessor::Run()
|
|||||||
AvRevertMmThreadCharacteristics(avTaskHandle);
|
AvRevertMmThreadCharacteristics(avTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSwapChainProcessor::RunCore()
|
void CSwapChainProcessor::SwapChainThreadCore()
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
|
Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
|
||||||
HRESULT hr = m_device->m_device.As(&dxgiDevice);
|
HRESULT hr = m_device->m_device.As(&dxgiDevice);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to get the dxgiDevice");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IDARG_IN_SWAPCHAINSETDEVICE setDevice = {};
|
IDARG_IN_SWAPCHAINSETDEVICE setDevice = {};
|
||||||
setDevice.pDevice = dxgiDevice.Get();
|
setDevice.pDevice = dxgiDevice.Get();
|
||||||
|
|
||||||
|
LOCK_CONTEXT();
|
||||||
hr = IddCxSwapChainSetDevice(m_hSwapChain, &setDevice);
|
hr = IddCxSwapChainSetDevice(m_hSwapChain, &setDevice);
|
||||||
if (FAILED(hr))
|
UNLOCK_CONTEXT();
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
DBGPRINT("IddCxSwapChainSetDevice Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT lastFrameNumber = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<IDXGIResource> acquiredBuffer;
|
ComPtr<IDXGIResource> acquiredBuffer;
|
||||||
IDARG_OUT_RELEASEANDACQUIREBUFFER buffer = {};
|
IDARG_OUT_RELEASEANDACQUIREBUFFER buffer = {};
|
||||||
|
|
||||||
|
LOCK_CONTEXT();
|
||||||
hr = IddCxSwapChainReleaseAndAcquireBuffer(m_hSwapChain, &buffer);
|
hr = IddCxSwapChainReleaseAndAcquireBuffer(m_hSwapChain, &buffer);
|
||||||
|
|
||||||
if (hr == E_PENDING)
|
if (hr == E_PENDING)
|
||||||
{
|
{
|
||||||
|
UNLOCK_CONTEXT();
|
||||||
HANDLE waitHandles[] =
|
HANDLE waitHandles[] =
|
||||||
{
|
{
|
||||||
m_newFrameEvent,
|
m_newFrameEvent,
|
||||||
@ -78,16 +103,132 @@ void CSwapChainProcessor::RunCore()
|
|||||||
}
|
}
|
||||||
else if (SUCCEEDED(hr))
|
else if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//acquiredBuffer.Attach(buffer.MetaData.pSurface);
|
if (buffer.MetaData.PresentationFrameNumber != lastFrameNumber)
|
||||||
|
{
|
||||||
|
lastFrameNumber = buffer.MetaData.PresentationFrameNumber;
|
||||||
|
if (m_copyCount < STAGING_TEXTURES)
|
||||||
|
{
|
||||||
|
acquiredBuffer.Attach(buffer.MetaData.pSurface);
|
||||||
|
SwapChainNewFrame(acquiredBuffer);
|
||||||
|
acquiredBuffer.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: process the frame
|
|
||||||
|
|
||||||
//acquiredBuffer.Reset();
|
|
||||||
hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
|
hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
|
||||||
|
UNLOCK_CONTEXT();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
UNLOCK_CONTEXT();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer)
|
||||||
|
{
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
|
||||||
|
if (FAILED(acquiredBuffer->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&texture)))
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to obtain the ID3D11Texture2D from the acquiredBuffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
texture->GetDesc(&desc);
|
||||||
|
|
||||||
|
if (!SetupStagingTexture(m_cpuTex[m_texWIndex], desc.Width, desc.Height, desc.Format))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_device->m_context->CopyResource(m_cpuTex[m_texWIndex].tex.Get(), texture.Get());
|
||||||
|
|
||||||
|
InterlockedAdd(&m_copyCount, 1);
|
||||||
|
if (++m_texWIndex == STAGING_TEXTURES)
|
||||||
|
m_texWIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD CALLBACK CSwapChainProcessor::_FrameThread(LPVOID arg)
|
||||||
|
{
|
||||||
|
reinterpret_cast<CSwapChainProcessor*>(arg)->FrameThread();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSwapChainProcessor::FrameThread()
|
||||||
|
{
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(m_terminateEvent.Get(), 0) == WAIT_OBJECT_0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!m_copyCount)
|
||||||
|
{
|
||||||
|
Sleep(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11_MAPPED_SUBRESOURCE map;
|
||||||
|
StagingTexture & t = m_cpuTex[m_texRIndex];
|
||||||
|
|
||||||
|
LOCK_CONTEXT();
|
||||||
|
HRESULT status = m_device->m_context->Map(t.tex.Get(), 0, D3D11_MAP_READ, D3D11_MAP_FLAG_DO_NOT_WAIT, &map);
|
||||||
|
UNLOCK_CONTEXT();
|
||||||
|
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
if (status == DXGI_ERROR_WAS_STILL_DRAWING)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DBGPRINT("Failed to map staging texture");
|
||||||
|
|
||||||
|
InterlockedAdd(&m_copyCount, -1);
|
||||||
|
if (++m_texRIndex == STAGING_TEXTURES)
|
||||||
|
m_texRIndex = 0;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_devContext->SendFrame(t.width, t.height, map.RowPitch, t.format, map.pData);
|
||||||
|
|
||||||
|
LOCK_CONTEXT();
|
||||||
|
m_device->m_context->Unmap(t.tex.Get(), 0);
|
||||||
|
UNLOCK_CONTEXT();
|
||||||
|
|
||||||
|
InterlockedAdd(&m_copyCount, -1);
|
||||||
|
if (++m_texRIndex == STAGING_TEXTURES)
|
||||||
|
m_texRIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSwapChainProcessor::SetupStagingTexture(StagingTexture & t, int width, int height, DXGI_FORMAT format)
|
||||||
|
{
|
||||||
|
if (t.width == width && t.height == height && t.format == format)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
t.tex.Reset();
|
||||||
|
t.width = width;
|
||||||
|
t.height = height;
|
||||||
|
t.format = format;
|
||||||
|
|
||||||
|
D3D11_TEXTURE2D_DESC desc = {};
|
||||||
|
desc.Width = width;
|
||||||
|
desc.Height = height;
|
||||||
|
desc.MipLevels = 1;
|
||||||
|
desc.ArraySize = 1;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.Usage = D3D11_USAGE_STAGING;
|
||||||
|
desc.Format = format;
|
||||||
|
desc.BindFlags = 0;
|
||||||
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||||
|
desc.MiscFlags = 0;
|
||||||
|
|
||||||
|
if (FAILED(m_device->m_device->CreateTexture2D(&desc, nullptr, &t.tex)))
|
||||||
|
{
|
||||||
|
DBGPRINT("Failed to create staging texture");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
@ -1,30 +1,55 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Direct3DDevice.h"
|
#include "Direct3DDevice.h"
|
||||||
|
#include "CIndirectDeviceContext.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
#include <IddCx.h>
|
#include <IddCx.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
|
#define STAGING_TEXTURES 3
|
||||||
|
|
||||||
class CSwapChainProcessor
|
class CSwapChainProcessor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
CIndirectDeviceContext * m_devContext;
|
||||||
IDDCX_SWAPCHAIN m_hSwapChain;
|
IDDCX_SWAPCHAIN m_hSwapChain;
|
||||||
std::shared_ptr<Direct3DDevice> m_device;
|
std::shared_ptr<Direct3DDevice> m_device;
|
||||||
HANDLE m_newFrameEvent;
|
HANDLE m_newFrameEvent;
|
||||||
|
|
||||||
Microsoft::WRL::Wrappers::HandleT<
|
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread[2];
|
||||||
Microsoft::WRL::Wrappers::HandleTraits::HANDLENullTraits> m_thread;
|
Wrappers::Event m_terminateEvent;
|
||||||
Microsoft::WRL::Wrappers::Event m_terminateEvent;
|
|
||||||
|
|
||||||
static DWORD CALLBACK RunThread(LPVOID argument);
|
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
||||||
|
static DWORD CALLBACK _FrameThread(LPVOID arg);
|
||||||
|
|
||||||
void Run();
|
void SwapChainThread();
|
||||||
void RunCore();
|
void SwapChainThreadCore();
|
||||||
|
void SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer);
|
||||||
|
|
||||||
|
void FrameThread();
|
||||||
|
|
||||||
|
struct StagingTexture
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
DXGI_FORMAT format;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11Texture2D> tex;
|
||||||
|
};
|
||||||
|
|
||||||
|
StagingTexture m_cpuTex[STAGING_TEXTURES] = {};
|
||||||
|
volatile LONG m_copyCount = 0;
|
||||||
|
volatile LONG m_contextLock = 0;
|
||||||
|
int m_texRIndex = 0;
|
||||||
|
int m_texWIndex = 0;
|
||||||
|
|
||||||
|
bool SetupStagingTexture(StagingTexture & t, int width, int height, DXGI_FORMAT format);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain,
|
CSwapChainProcessor(CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||||
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent);
|
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent);
|
||||||
~CSwapChainProcessor();
|
~CSwapChainProcessor();
|
||||||
};
|
};
|
@ -9,6 +9,7 @@
|
|||||||
#include <avrt.h>
|
#include <avrt.h>
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
|
|
||||||
|
#include "Debug.h"
|
||||||
#include "CIndirectDeviceContext.h"
|
#include "CIndirectDeviceContext.h"
|
||||||
#include "CIndirectMonitorContext.h"
|
#include "CIndirectMonitorContext.h"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user