mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-04-24 23:56:26 +00:00
[idd] rewrite to support DirectX12 copy
This commit is contained in:
parent
62c075cfb5
commit
8b198091ce
@ -18,9 +18,10 @@
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Direct3DDevice.h"
|
||||
#include "CD3D11Device.h"
|
||||
#include "Debug.h"
|
||||
|
||||
HRESULT Direct3DDevice::Init()
|
||||
HRESULT CD3D11Device::Init()
|
||||
{
|
||||
HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&m_factory));
|
||||
if (FAILED(hr))
|
||||
@ -29,18 +30,37 @@ HRESULT Direct3DDevice::Init()
|
||||
hr = m_factory->EnumAdapterByLuid(m_adapterLuid, IID_PPV_ARGS(&m_adapter));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// only 11.1 supports DX12 interoperabillity
|
||||
static const D3D_FEATURE_LEVEL featureLevels[] =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_11_1
|
||||
};
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
|
||||
ComPtr<ID3D11Device> device;
|
||||
ComPtr<ID3D11DeviceContext> context;
|
||||
hr = D3D11CreateDevice(
|
||||
m_adapter.Get(),
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
nullptr,
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
nullptr,
|
||||
0,
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG,
|
||||
featureLevels,
|
||||
ARRAYSIZE(featureLevels),
|
||||
D3D11_SDK_VERSION,
|
||||
&m_device,
|
||||
nullptr,
|
||||
&m_context);
|
||||
&device,
|
||||
&featureLevel,
|
||||
&context);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
DBGPRINT("Feature Level: 0x%x", featureLevel);
|
||||
|
||||
hr = device.As(&m_device);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = context.As(&m_context);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
@ -26,21 +26,29 @@
|
||||
#include <dxgi1_5.h>
|
||||
#include <d3d11_4.h>
|
||||
|
||||
struct Direct3DDevice
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
struct CD3D11Device
|
||||
{
|
||||
Direct3DDevice(LUID adapterLuid) :
|
||||
private:
|
||||
LUID m_adapterLuid;
|
||||
ComPtr<IDXGIFactory5 > m_factory;
|
||||
ComPtr<IDXGIAdapter1 > m_adapter;
|
||||
ComPtr<ID3D11Device5 > m_device;
|
||||
ComPtr<ID3D11DeviceContext4> m_context;
|
||||
|
||||
public:
|
||||
CD3D11Device(LUID adapterLuid) :
|
||||
m_adapterLuid(adapterLuid) {};
|
||||
|
||||
Direct3DDevice()
|
||||
CD3D11Device()
|
||||
{
|
||||
m_adapterLuid = LUID{};
|
||||
}
|
||||
|
||||
HRESULT Init();
|
||||
|
||||
LUID m_adapterLuid;
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory5 > m_factory;
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter1 > m_adapter;
|
||||
Microsoft::WRL::ComPtr<ID3D11Device > m_device;
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_context;
|
||||
ComPtr<ID3D11Device5> GetDevice() { return m_device; }
|
||||
|
||||
ComPtr<ID3D11DeviceContext4> GetContext() { return m_context; }
|
||||
};
|
115
idd/LGIdd/CD3D12CommandQueue.cpp
Normal file
115
idd/LGIdd/CD3D12CommandQueue.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include "CD3D12CommandQueue.h"
|
||||
#include "Debug.h"
|
||||
|
||||
bool CD3D12CommandQueue::Init(ID3D12Device3 * device, D3D12_COMMAND_LIST_TYPE type, const WCHAR* name)
|
||||
{
|
||||
HRESULT hr;
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
|
||||
queueDesc.Type = type;
|
||||
queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
|
||||
hr = device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_queue));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the CommandQueue (%ls)", name);
|
||||
return false;
|
||||
}
|
||||
m_queue->SetName(name);
|
||||
|
||||
hr = device->CreateCommandAllocator(type, IID_PPV_ARGS(&m_allocator));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the CommandAllocator (%ls)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = device->CreateCommandList(0, type, m_allocator.Get(), NULL, IID_PPV_ARGS(&m_gfxList));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the Graphics CommandList (%ls)", name);
|
||||
return false;
|
||||
}
|
||||
m_gfxList->SetName(name);
|
||||
|
||||
m_cmdList = m_gfxList;
|
||||
if (!m_cmdList)
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to get the CommandList (%ls)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the Fence (%ls)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_event.Attach(CreateEvent(NULL, FALSE, FALSE, NULL));
|
||||
if (m_event.Get() == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DBGPRINT_HR(GetLastError(), "Failed to create the completion event (%ls)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_name = name;
|
||||
m_fenceValue = 0;
|
||||
DBGPRINT("Created CD3D12CommandQueue(%ls)", name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CD3D12CommandQueue::Execute()
|
||||
{
|
||||
HRESULT hr = m_gfxList->Close();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to close the command list (%ls)", m_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12CommandList * lists[] = { m_cmdList.Get() };
|
||||
m_queue->ExecuteCommandLists(1, lists);
|
||||
|
||||
m_queue->Signal(m_fence.Get(), ++m_fenceValue);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to set the fence signal (%ls)", m_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CD3D12CommandQueue::Wait()
|
||||
{
|
||||
if (m_fence->GetCompletedValue() >= m_fenceValue)
|
||||
return;
|
||||
|
||||
m_fence->SetEventOnCompletion(m_fenceValue, m_event.Get());
|
||||
WaitForSingleObject(m_event.Get(), INFINITE);
|
||||
}
|
||||
|
||||
bool CD3D12CommandQueue::Reset()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = m_allocator->Reset();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to reset the command allocator (%ls)", m_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = m_gfxList->Reset(m_allocator.Get(), NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to reset the graphics command list (%ls)", m_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
36
idd/LGIdd/CD3D12CommandQueue.h
Normal file
36
idd/LGIdd/CD3D12CommandQueue.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <wdf.h>
|
||||
#include <wrl.h>
|
||||
#include <d3d12.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
class CD3D12CommandQueue
|
||||
{
|
||||
private:
|
||||
const WCHAR * m_name = nullptr;
|
||||
|
||||
ComPtr<ID3D12CommandQueue > m_queue;
|
||||
ComPtr<ID3D12CommandAllocator > m_allocator;
|
||||
ComPtr<ID3D12GraphicsCommandList> m_gfxList;
|
||||
ComPtr<ID3D12CommandList > m_cmdList;
|
||||
ComPtr<ID3D12Fence > m_fence;
|
||||
|
||||
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_event;
|
||||
UINT64 m_fenceValue = 0;
|
||||
|
||||
public:
|
||||
bool Init(ID3D12Device3 * device, D3D12_COMMAND_LIST_TYPE type, const WCHAR * name);
|
||||
|
||||
bool Execute();
|
||||
|
||||
void Wait();
|
||||
|
||||
bool Reset();
|
||||
|
||||
ComPtr<ID3D12CommandQueue > GetCmdQueue() { return m_queue; }
|
||||
ComPtr<ID3D12GraphicsCommandList> GetGfxList() { return m_gfxList; }
|
||||
};
|
||||
|
169
idd/LGIdd/CD3D12Device.cpp
Normal file
169
idd/LGIdd/CD3D12Device.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#include "CD3D12Device.h"
|
||||
#include "Debug.h"
|
||||
|
||||
CD3D12Device::CD3D12Device(LUID adapterLuid) :
|
||||
m_adapterLuid(adapterLuid),
|
||||
m_debug(false),
|
||||
m_indirectCopy(false)
|
||||
{
|
||||
if (m_debug)
|
||||
{
|
||||
HRESULT hr = D3D12GetDebugInterface(IID_PPV_ARGS(&m_dxDebug));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to get the debug interface");
|
||||
return;
|
||||
}
|
||||
|
||||
m_dxDebug->EnableDebugLayer();
|
||||
m_dxDebug->SetEnableGPUBasedValidation(TRUE);
|
||||
m_dxDebug->SetEnableSynchronizedCommandQueueValidation(TRUE);
|
||||
m_dxDebug->SetForceLegacyBarrierValidation(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void CALLBACK _D3D12DebugCallback(
|
||||
D3D12_MESSAGE_CATEGORY category,
|
||||
D3D12_MESSAGE_SEVERITY severity,
|
||||
D3D12_MESSAGE_ID id,
|
||||
LPCSTR description,
|
||||
void *context
|
||||
)
|
||||
{
|
||||
(void)context;
|
||||
|
||||
DBGPRINT("category:%d severity:%d id:%d desc:%s",
|
||||
category,
|
||||
severity,
|
||||
id,
|
||||
description);
|
||||
}
|
||||
|
||||
bool CD3D12Device::Init(CIVSHMEM &ivshmem, UINT64 &alignSize)
|
||||
{
|
||||
reInit:
|
||||
HRESULT hr;
|
||||
|
||||
hr = CreateDXGIFactory2(m_debug ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&m_factory));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the DXGI factory");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = m_factory->EnumAdapterByLuid(m_adapterLuid, IID_PPV_ARGS(&m_adapter));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to enumerate the adapter");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = D3D12CreateDevice(m_adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&m_device));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the DirectX12 device");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_debug)
|
||||
{
|
||||
hr = m_device.As(&m_infoQueue);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to get the ID3D12InfoQueue1 interface");
|
||||
//non-fatal do not exit
|
||||
}
|
||||
else
|
||||
m_infoQueue->RegisterMessageCallback(
|
||||
_D3D12DebugCallback, D3D12_MESSAGE_CALLBACK_FLAG_NONE, NULL, &m_callbackCookie);
|
||||
}
|
||||
|
||||
if (!m_indirectCopy)
|
||||
{
|
||||
hr = m_device->OpenExistingHeapFromAddress(ivshmem.GetMem(), IID_PPV_ARGS(&m_ivshmemHeap));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to open IVSHMEM as a D3D12Heap");
|
||||
return false;
|
||||
}
|
||||
m_ivshmemHeap->SetName(L"IVSHMEM");
|
||||
|
||||
D3D12_HEAP_DESC heapDesc = m_ivshmemHeap->GetDesc();
|
||||
alignSize = heapDesc.Alignment;
|
||||
|
||||
// test that the heap is usable
|
||||
if (!HeapTest())
|
||||
{
|
||||
DBGPRINT("Unable to create resources in the IVSHMEM heap, falling back to indirect copy");
|
||||
|
||||
// failure often results in the device being removed and we need to completely reinit when this occurs
|
||||
m_indirectCopy = true;
|
||||
m_device.Reset();
|
||||
m_adapter.Reset();
|
||||
m_factory.Reset();
|
||||
goto reInit;
|
||||
}
|
||||
|
||||
DBGPRINT("Using IVSHMEM as a D3D12Heap");
|
||||
}
|
||||
|
||||
if (!m_copyQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COPY, L"Copy"))
|
||||
return false;
|
||||
|
||||
//if (!m_computeQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COMPUTE, L"Compute"))
|
||||
//return false;
|
||||
|
||||
DBGPRINT("Created CD3D12Device");
|
||||
return true;
|
||||
}
|
||||
|
||||
void CD3D12Device::DeInit()
|
||||
{
|
||||
if (m_debug && m_infoQueue)
|
||||
m_infoQueue->UnregisterMessageCallback(m_callbackCookie);
|
||||
m_infoQueue.Reset();
|
||||
}
|
||||
|
||||
bool CD3D12Device::HeapTest()
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc = {};
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = 1048576;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
ComPtr<ID3D12Resource> resource;
|
||||
hr = m_device->CreatePlacedResource(
|
||||
m_ivshmemHeap.Get(),
|
||||
0,
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
IID_PPV_ARGS(&resource));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the ivshmem ID3D12Resource");
|
||||
return false;
|
||||
}
|
||||
resource->SetName(L"HeapTest");
|
||||
|
||||
/* the above may succeed even if there was a fault, as such we also need to check
|
||||
* check if the device was removed */
|
||||
hr = m_device->GetDeviceRemovedReason();
|
||||
if (hr != S_OK)
|
||||
{
|
||||
DBGPRINT_HR(hr, "Device Removed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
48
idd/LGIdd/CD3D12Device.h
Normal file
48
idd/LGIdd/CD3D12Device.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <wdf.h>
|
||||
#include <wrl.h>
|
||||
#include <dxgi1_5.h>
|
||||
#include <d3d12.h>
|
||||
|
||||
#include "CIVSHMEM.h"
|
||||
#include "CD3D12CommandQueue.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
struct CD3D12Device
|
||||
{
|
||||
private:
|
||||
LUID m_adapterLuid;
|
||||
bool m_debug;
|
||||
bool m_indirectCopy;
|
||||
|
||||
ComPtr<ID3D12Debug6 > m_dxDebug;
|
||||
ComPtr<ID3D12InfoQueue1> m_infoQueue;
|
||||
DWORD m_callbackCookie;
|
||||
|
||||
ComPtr<IDXGIFactory5> m_factory;
|
||||
ComPtr<IDXGIAdapter1> m_adapter;
|
||||
ComPtr<ID3D12Device3> m_device;
|
||||
ComPtr<ID3D12Heap > m_ivshmemHeap;
|
||||
|
||||
CD3D12CommandQueue m_copyQueue;
|
||||
CD3D12CommandQueue m_computeQueue;
|
||||
|
||||
bool HeapTest();
|
||||
|
||||
public:
|
||||
CD3D12Device(LUID adapterLUID);
|
||||
~CD3D12Device() { DeInit(); }
|
||||
|
||||
bool Init(CIVSHMEM &ivshmem, UINT64 &alignSize);
|
||||
void DeInit();
|
||||
|
||||
ComPtr<ID3D12Device3> GetDevice() { return m_device; }
|
||||
ComPtr<ID3D12Heap > GetHeap() { return m_ivshmemHeap; }
|
||||
bool IsIndirectCopy() { return m_indirectCopy; }
|
||||
|
||||
CD3D12CommandQueue& GetCopyQueue() { return m_copyQueue; }
|
||||
CD3D12CommandQueue& GetComputeQueue() { return m_computeQueue; }
|
||||
};
|
31
idd/LGIdd/CFrameBufferPool.cpp
Normal file
31
idd/LGIdd/CFrameBufferPool.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "CFrameBufferPool.h"
|
||||
#include "CSwapChainProcessor.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void CFrameBufferPool::Init(CSwapChainProcessor * swapChain)
|
||||
{
|
||||
m_swapChain = swapChain;
|
||||
}
|
||||
|
||||
void CFrameBufferPool::Reset()
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(m_buffers); ++i)
|
||||
m_buffers[i].Reset();
|
||||
}
|
||||
|
||||
CFrameBufferResource * CFrameBufferPool::Get(const CIndirectDeviceContext::PreparedFrameBuffer& buffer, size_t minSize)
|
||||
{
|
||||
if (buffer.frameIndex > ARRAYSIZE(m_buffers) - 1)
|
||||
return nullptr;
|
||||
|
||||
CFrameBufferResource* fbr = &m_buffers[buffer.frameIndex];
|
||||
if (!fbr->IsValid() || fbr->GetBase() != buffer.mem || fbr->GetSize() < minSize)
|
||||
{
|
||||
fbr->Reset();
|
||||
if (!fbr->Init(m_swapChain, buffer.mem, minSize))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fbr;
|
||||
}
|
20
idd/LGIdd/CFrameBufferPool.h
Normal file
20
idd/LGIdd/CFrameBufferPool.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "CFrameBufferResource.h"
|
||||
#include "CIndirectDeviceContext.h"
|
||||
#include "common/KVMFR.h"
|
||||
|
||||
//class CSwapChainProcessor;
|
||||
|
||||
class CFrameBufferPool
|
||||
{
|
||||
CSwapChainProcessor * m_swapChain;
|
||||
|
||||
CFrameBufferResource m_buffers[LGMP_Q_FRAME_LEN];
|
||||
|
||||
public:
|
||||
void Init(CSwapChainProcessor * swapChain);
|
||||
void Reset();
|
||||
|
||||
CFrameBufferResource* CFrameBufferPool::Get(const CIndirectDeviceContext::PreparedFrameBuffer& buffer, size_t minSize);
|
||||
};
|
91
idd/LGIdd/CFrameBufferResource.cpp
Normal file
91
idd/LGIdd/CFrameBufferResource.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "CFrameBufferResource.h"
|
||||
#include "CSwapChainProcessor.h"
|
||||
#include "Debug.h"
|
||||
|
||||
bool CFrameBufferResource::Init(CSwapChainProcessor * swapChain, uint8_t * base, size_t size)
|
||||
{
|
||||
if (size > swapChain->GetDevice()->GetMaxFrameSize())
|
||||
{
|
||||
DBGPRINT("Frame size of %lu is too large to fit in available shared ram");
|
||||
return false;
|
||||
}
|
||||
|
||||
// nothing to do if the resource already exists and is large enough
|
||||
if (m_base == base && m_size >= size)
|
||||
return true;
|
||||
|
||||
Reset();
|
||||
|
||||
D3D12_RESOURCE_DESC desc = {};
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Width = size;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
HRESULT hr;
|
||||
const WCHAR * resName;
|
||||
|
||||
if (swapChain->GetD3D12Device()->IsIndirectCopy())
|
||||
{
|
||||
DBGPRINT("Creating standard resource for %p", base);
|
||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
||||
heapProps.Type = D3D12_HEAP_TYPE_READBACK;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProps.CreationNodeMask = 1;
|
||||
heapProps.VisibleNodeMask = 1;
|
||||
|
||||
hr = swapChain->GetD3D12Device()->GetDevice()->CreateCommittedResource(
|
||||
&heapProps,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
IID_PPV_ARGS(&m_res)
|
||||
);
|
||||
resName = L"STAGING";
|
||||
}
|
||||
else
|
||||
{
|
||||
DBGPRINT("Creating ivshmem resource for %p", base);
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
|
||||
|
||||
hr = swapChain->GetD3D12Device()->GetDevice()->CreatePlacedResource(
|
||||
swapChain->GetD3D12Device()->GetHeap().Get(),
|
||||
(uintptr_t)base - (uintptr_t)swapChain->GetDevice()->GetIVSHMEM().GetMem(),
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
IID_PPV_ARGS(&m_res)
|
||||
);
|
||||
resName = L"IVSHMEM";
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the FrameBuffer ID3D12Resource");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_res->SetName(resName);
|
||||
|
||||
m_base = base;
|
||||
m_size = size;
|
||||
m_valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFrameBufferResource::Reset()
|
||||
{
|
||||
m_base = nullptr;
|
||||
m_size = 0;
|
||||
m_res.Reset();
|
||||
m_valid = false;
|
||||
}
|
30
idd/LGIdd/CFrameBufferResource.h
Normal file
30
idd/LGIdd/CFrameBufferResource.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <wdf.h>
|
||||
#include <wrl.h>
|
||||
#include <d3d12.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class CSwapChainProcessor;
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
class CFrameBufferResource
|
||||
{
|
||||
private:
|
||||
bool m_valid;
|
||||
uint8_t * m_base;
|
||||
size_t m_size;
|
||||
ComPtr<ID3D12Resource> m_res;
|
||||
|
||||
public:
|
||||
bool Init(CSwapChainProcessor * swapChain, uint8_t * base, size_t size);
|
||||
void Reset();
|
||||
|
||||
bool IsValid() { return m_valid; }
|
||||
uint8_t * GetBase() { return m_base; }
|
||||
size_t GetSize() { return m_size; }
|
||||
|
||||
ComPtr<ID3D12Resource> Get() { return m_res; }
|
||||
};
|
@ -102,7 +102,7 @@ bool CIVSHMEM::Init()
|
||||
{
|
||||
DWORD bus = it->busAddr >> 32;
|
||||
DWORD addr = it->busAddr & 0xFFFFFFFF;
|
||||
DBGPRINT("IVSHMEM %u%c on bus 0x%lx, device 0x%lx, function 0x%lx\n",
|
||||
DBGPRINT("IVSHMEM %u%c on bus 0x%lx, device 0x%lx, function 0x%lx",
|
||||
i, i == shmDevice ? '*' : ' ', bus, addr >> 16, addr & 0xFFFF);
|
||||
|
||||
if (i == shmDevice)
|
||||
|
@ -40,29 +40,9 @@ static const struct LGMPQueueConfig POINTER_QUEUE_CONFIG =
|
||||
1000 //subTimeout
|
||||
};
|
||||
|
||||
CIndirectDeviceContext::~CIndirectDeviceContext()
|
||||
{
|
||||
if (m_lgmp == nullptr)
|
||||
return;
|
||||
|
||||
if (m_lgmpTimer)
|
||||
{
|
||||
WdfTimerStop(m_lgmpTimer, TRUE);
|
||||
m_lgmpTimer = nullptr;
|
||||
}
|
||||
|
||||
for(int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||
lgmpHostMemFree(&m_frameMemory[i]);
|
||||
for (int i = 0; i < LGMP_Q_POINTER_LEN; ++i)
|
||||
lgmpHostMemFree(&m_pointerMemory[i]);
|
||||
for (int i = 0; i < POINTER_SHAPE_BUFFERS; ++i)
|
||||
lgmpHostMemFree(&m_pointerShapeMemory[i]);
|
||||
lgmpHostFree(&m_lgmp);
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::InitAdapter()
|
||||
{
|
||||
if (!SetupLGMP())
|
||||
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
||||
return;
|
||||
|
||||
IDDCX_ADAPTER_CAPS caps = {};
|
||||
@ -193,11 +173,15 @@ void CIndirectDeviceContext::FinishInit(UINT connectorIndex)
|
||||
status = IddCxMonitorArrival(m_monitor, &out);
|
||||
}
|
||||
|
||||
bool CIndirectDeviceContext::SetupLGMP()
|
||||
bool CIndirectDeviceContext::SetupLGMP(size_t alignSize)
|
||||
{
|
||||
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
||||
return false;
|
||||
// this may get called multiple times as we need to delay calling it until
|
||||
// we can determine the required alignment from the GPU in use
|
||||
if (m_lgmp)
|
||||
return true;
|
||||
|
||||
m_alignSize = alignSize;
|
||||
|
||||
std::stringstream ss;
|
||||
{
|
||||
KVMFR kvmfr = {};
|
||||
@ -310,13 +294,13 @@ bool CIndirectDeviceContext::SetupLGMP()
|
||||
}
|
||||
|
||||
m_maxFrameSize = lgmpHostMemAvail(m_lgmp);
|
||||
m_maxFrameSize = (m_maxFrameSize -(CPlatformInfo::GetPageSize() - 1)) & ~(CPlatformInfo::GetPageSize() - 1);
|
||||
m_maxFrameSize = (m_maxFrameSize -(m_alignSize - 1)) & ~(m_alignSize - 1);
|
||||
m_maxFrameSize /= LGMP_Q_FRAME_LEN;
|
||||
DBGPRINT("Max Frame Size: %u MiB\n", (unsigned int)(m_maxFrameSize / 1048576LL));
|
||||
DBGPRINT("Max Frame Size: %u MiB", (unsigned int)(m_maxFrameSize / 1048576LL));
|
||||
|
||||
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||
if ((status = lgmpHostMemAllocAligned(m_lgmp, (uint32_t)m_maxFrameSize,
|
||||
(uint32_t)CPlatformInfo::GetPageSize(), &m_frameMemory[i])) != LGMP_OK)
|
||||
(uint32_t)m_alignSize, &m_frameMemory[i])) != LGMP_OK)
|
||||
{
|
||||
DBGPRINT("lgmpHostMemAllocAligned Failed (Frame): %s", lgmpStatusString(status));
|
||||
return false;
|
||||
@ -353,6 +337,26 @@ bool CIndirectDeviceContext::SetupLGMP()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::DeInitLGMP()
|
||||
{
|
||||
if (m_lgmp == nullptr)
|
||||
return;
|
||||
|
||||
if (m_lgmpTimer)
|
||||
{
|
||||
WdfTimerStop(m_lgmpTimer, TRUE);
|
||||
m_lgmpTimer = nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||
lgmpHostMemFree(&m_frameMemory[i]);
|
||||
for (int i = 0; i < LGMP_Q_POINTER_LEN; ++i)
|
||||
lgmpHostMemFree(&m_pointerMemory[i]);
|
||||
for (int i = 0; i < POINTER_SHAPE_BUFFERS; ++i)
|
||||
lgmpHostMemFree(&m_pointerShapeMemory[i]);
|
||||
lgmpHostFree(&m_lgmp);
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::LGMPTimer()
|
||||
{
|
||||
LGMP_STATUS status;
|
||||
@ -399,10 +403,22 @@ void CIndirectDeviceContext::LGMPTimer()
|
||||
ResendCursor();
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FORMAT format, void* data)
|
||||
//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)
|
||||
|
||||
CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrameBuffer(int width, int height, int pitch, DXGI_FORMAT format)
|
||||
{
|
||||
PreparedFrameBuffer result = {};
|
||||
|
||||
if (!m_lgmp || !m_frameQueue)
|
||||
return;
|
||||
return result;
|
||||
|
||||
if (m_width != width || m_height != height || m_pitch != pitch || m_format != format)
|
||||
{
|
||||
@ -413,13 +429,15 @@ void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FO
|
||||
++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]);
|
||||
|
||||
// wait until there is room in the queue
|
||||
while (lgmpHostQueuePending(m_frameQueue) == LGMP_Q_FRAME_LEN)
|
||||
Sleep(0);
|
||||
|
||||
int bpp = 4;
|
||||
switch (format)
|
||||
{
|
||||
@ -434,19 +452,9 @@ void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FO
|
||||
|
||||
default:
|
||||
DBGPRINT("Unsuppoted DXGI format");
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
//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;
|
||||
@ -457,18 +465,30 @@ void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FO
|
||||
fi->frameHeight = height;
|
||||
fi->stride = width * bpp;
|
||||
fi->pitch = pitch;
|
||||
fi->offset = (uint32_t)(CPlatformInfo::GetPageSize() - sizeof(FrameBuffer));
|
||||
fi->offset = (uint32_t)(m_alignSize - sizeof(FrameBuffer));
|
||||
fi->flags = 0;
|
||||
fi->rotation = FRAME_ROT_0;
|
||||
|
||||
fi->damageRectsCount = 0;
|
||||
|
||||
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)fi) + fi->offset);
|
||||
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;
|
||||
|
||||
result.frameIndex = m_frameIndex;
|
||||
result.mem = fb->data;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::FinalizeFrameBuffer()
|
||||
{
|
||||
if (!m_lgmp || !m_frameQueue)
|
||||
return;
|
||||
|
||||
KVMFRFrame * fi = (KVMFRFrame*)lgmpHostMemPtr(m_frameMemory[m_frameIndex]);
|
||||
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)fi) + fi->offset);
|
||||
fb->wp = m_height * m_pitch;
|
||||
}
|
||||
|
||||
void CIndirectDeviceContext::SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info, const BYTE * data)
|
||||
@ -504,7 +524,7 @@ void CIndirectDeviceContext::SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info, co
|
||||
if (info.CursorShapeInfo.CursorType != IDDCX_CURSOR_SHAPE_TYPE_UNINITIALIZED)
|
||||
{
|
||||
memcpy(cursor + 1, data,
|
||||
(size_t)(info.CursorShapeInfo.Height * info.CursorShapeInfo.Pitch));
|
||||
(size_t)info.CursorShapeInfo.Height * info.CursorShapeInfo.Pitch);
|
||||
|
||||
cursor->hx = (int8_t )info.CursorShapeInfo.XHot;
|
||||
cursor->hy = (int8_t )info.CursorShapeInfo.YHot;
|
||||
|
@ -56,6 +56,7 @@ private:
|
||||
bool m_cursorVisible = false;
|
||||
int m_cursorX = 0, m_cursorY = 0;
|
||||
|
||||
size_t m_alignSize = 0;
|
||||
size_t m_maxFrameSize = 0;
|
||||
int m_frameIndex = 0;
|
||||
uint32_t m_formatVer = 0;
|
||||
@ -67,7 +68,7 @@ private:
|
||||
int m_pitch = 0;
|
||||
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
bool SetupLGMP();
|
||||
void DeInitLGMP();
|
||||
void LGMPTimer();
|
||||
void ResendCursor();
|
||||
|
||||
@ -75,14 +76,29 @@ public:
|
||||
CIndirectDeviceContext(_In_ WDFDEVICE wdfDevice) :
|
||||
m_wdfDevice(wdfDevice) {};
|
||||
|
||||
virtual ~CIndirectDeviceContext();
|
||||
virtual ~CIndirectDeviceContext() { DeInitLGMP(); }
|
||||
|
||||
bool SetupLGMP(size_t alignSize);
|
||||
|
||||
void InitAdapter();
|
||||
|
||||
void FinishInit(UINT connectorIndex);
|
||||
|
||||
void SendFrame(int width, int height, int pitch, DXGI_FORMAT format, void* data);
|
||||
size_t GetAlignSize() { return m_alignSize; }
|
||||
size_t GetMaxFrameSize() { return m_maxFrameSize; }
|
||||
|
||||
struct PreparedFrameBuffer
|
||||
{
|
||||
unsigned frameIndex;
|
||||
uint8_t* mem;
|
||||
};
|
||||
|
||||
PreparedFrameBuffer PrepareFrameBuffer(int width, int height, int pitch, DXGI_FORMAT format);
|
||||
void FinalizeFrameBuffer();
|
||||
|
||||
void SendCursor(const IDARG_OUT_QUERY_HWCURSOR & info, const BYTE * data);
|
||||
|
||||
CIVSHMEM &GetIVSHMEM() { return m_ivshmem; }
|
||||
};
|
||||
|
||||
struct CIndirectDeviceContextWrapper
|
||||
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "CIndirectMonitorContext.h"
|
||||
#include "Direct3DDevice.h"
|
||||
#include "CPlatformInfo.h"
|
||||
#include "Debug.h"
|
||||
|
||||
CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device) :
|
||||
@ -28,7 +28,6 @@ CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIn
|
||||
{
|
||||
m_terminateEvent .Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||
m_cursorDataEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||
m_thread.Attach(CreateThread(nullptr, 0, _CursorThread, this, 0, nullptr));
|
||||
m_shapeBuffer = new BYTE[512 * 512 * 4];
|
||||
}
|
||||
|
||||
@ -42,14 +41,27 @@ CIndirectMonitorContext::~CIndirectMonitorContext()
|
||||
void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent)
|
||||
{
|
||||
m_swapChain.reset();
|
||||
auto device = std::make_shared<Direct3DDevice>(renderAdapter);
|
||||
if (FAILED(device->Init()))
|
||||
m_dx11Device = std::make_shared<CD3D11Device>(renderAdapter);
|
||||
if (FAILED(m_dx11Device->Init()))
|
||||
{
|
||||
WdfObjectDelete(swapChain);
|
||||
return;
|
||||
}
|
||||
|
||||
m_swapChain.reset(new CSwapChainProcessor(m_devContext, swapChain, device, newFrameEvent));
|
||||
UINT64 alignSize = CPlatformInfo::GetPageSize();
|
||||
m_dx12Device = std::make_shared<CD3D12Device>(renderAdapter);
|
||||
if (!m_dx12Device->Init(m_devContext->GetIVSHMEM(), alignSize))
|
||||
{
|
||||
WdfObjectDelete(swapChain);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_devContext->SetupLGMP(alignSize))
|
||||
{
|
||||
WdfObjectDelete(swapChain);
|
||||
DBGPRINT("SetupLGMP failed");
|
||||
return;
|
||||
}
|
||||
|
||||
IDARG_IN_SETUP_HWCURSOR c = {};
|
||||
c.CursorInfo.Size = sizeof(c.CursorInfo);
|
||||
@ -60,12 +72,21 @@ void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID re
|
||||
c.hNewCursorDataAvailable = m_cursorDataEvent.Get();
|
||||
NTSTATUS status = IddCxMonitorSetupHardwareCursor(m_monitor, &c);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
WdfObjectDelete(swapChain);
|
||||
DBGPRINT("IddCxMonitorSetupHardwareCursor Failed: %08x", status);
|
||||
return;
|
||||
}
|
||||
|
||||
m_swapChain.reset(new CSwapChainProcessor(m_devContext, swapChain, m_dx11Device, m_dx12Device, newFrameEvent));
|
||||
m_thread.Attach(CreateThread(nullptr, 0, _CursorThread, this, 0, nullptr));
|
||||
}
|
||||
|
||||
void CIndirectMonitorContext::UnassignSwapChain()
|
||||
{
|
||||
m_swapChain.reset();
|
||||
m_swapChain.reset();
|
||||
m_dx11Device.reset();
|
||||
m_dx12Device.reset();
|
||||
}
|
||||
|
||||
DWORD CALLBACK CIndirectMonitorContext::_CursorThread(LPVOID arg)
|
||||
|
@ -34,6 +34,10 @@ class CIndirectMonitorContext
|
||||
{
|
||||
private:
|
||||
IDDCX_MONITOR m_monitor;
|
||||
|
||||
std::shared_ptr<CD3D11Device> m_dx11Device;
|
||||
std::shared_ptr<CD3D12Device> m_dx12Device;
|
||||
|
||||
CIndirectDeviceContext * m_devContext;
|
||||
std::unique_ptr<CSwapChainProcessor> m_swapChain;
|
||||
|
||||
|
127
idd/LGIdd/CInteropResource.cpp
Normal file
127
idd/LGIdd/CInteropResource.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include "CInteropResource.h"
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
bool CInteropResource::Init(std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device, ComPtr<ID3D11Texture2D> srcTex)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_TEXTURE2D_DESC srcDesc;
|
||||
srcTex->GetDesc(&srcDesc);
|
||||
|
||||
ComPtr<IDXGIResource1> rSrcTex;
|
||||
hr = srcTex.As(&rSrcTex);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to obtain the IDXGIResource1 interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE h;
|
||||
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> sharedHandle;
|
||||
hr = rSrcTex->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ, NULL, &h);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the shared handle");
|
||||
return false;
|
||||
}
|
||||
sharedHandle.Attach(h);
|
||||
|
||||
ComPtr<ID3D12Resource> dst;
|
||||
hr = dx12Device->GetDevice()->OpenSharedHandle(sharedHandle.Get(), IID_PPV_ARGS(&dst));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to open the D3D12Resource from the handle");
|
||||
return false;
|
||||
}
|
||||
|
||||
sharedHandle.Close();
|
||||
|
||||
ComPtr<ID3D11Fence> d11Fence;
|
||||
hr = dx11Device->GetDevice()->CreateFence(0, D3D11_FENCE_FLAG_SHARED, IID_PPV_ARGS(&d11Fence));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the d3d11 fence");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = d11Fence->CreateSharedHandle(NULL, GENERIC_ALL, NULL, &h);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to create the d3d11 fence shared handle");
|
||||
return false;
|
||||
}
|
||||
sharedHandle.Attach(h);
|
||||
|
||||
ComPtr<ID3D12Fence> d12Fence;
|
||||
hr = dx12Device->GetDevice()->OpenSharedHandle(sharedHandle.Get(), IID_PPV_ARGS(&d12Fence));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT_HR(hr, "Failed to open the D3D12Fence from the handle");
|
||||
return false;
|
||||
}
|
||||
|
||||
sharedHandle.Close();
|
||||
|
||||
m_dx11Device = dx11Device;
|
||||
m_dx12Device = dx12Device;
|
||||
|
||||
memcpy(&m_format, &srcDesc, sizeof(m_format));
|
||||
m_srcTex = srcTex.Get();
|
||||
m_d12Res = dst;
|
||||
m_d11Fence = d11Fence;
|
||||
m_d12Fence = d12Fence;
|
||||
m_fenceValue = 0;
|
||||
m_ready = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CInteropResource::Reset()
|
||||
{
|
||||
m_ready = false;
|
||||
m_fenceValue = 0;
|
||||
m_d12Fence.Reset();
|
||||
m_d11Fence.Reset();
|
||||
m_d12Res .Reset();
|
||||
m_srcTex = NULL;
|
||||
memset(&m_format, 0, sizeof(m_format));
|
||||
|
||||
m_dx12Device.reset();
|
||||
m_dx11Device.reset();
|
||||
}
|
||||
|
||||
bool CInteropResource::Compare(const ComPtr<ID3D11Texture2D>& srcTex)
|
||||
{
|
||||
if (srcTex.Get() != m_srcTex)
|
||||
return false;
|
||||
|
||||
D3D11_TEXTURE2D_DESC format;
|
||||
srcTex->GetDesc(&format);
|
||||
|
||||
return
|
||||
m_format.Width == format.Width &&
|
||||
m_format.Height == format.Height &&
|
||||
m_format.Format == format.Format;
|
||||
}
|
||||
|
||||
void CInteropResource::Signal()
|
||||
{
|
||||
++m_fenceValue;
|
||||
m_dx11Device->GetContext()->Signal(m_d11Fence.Get(), m_fenceValue);
|
||||
}
|
||||
|
||||
void CInteropResource::Sync(CD3D12CommandQueue& queue)
|
||||
{
|
||||
if (m_d11Fence->GetCompletedValue() < m_fenceValue)
|
||||
queue.GetCmdQueue()->Wait(m_d12Fence.Get(), m_fenceValue);
|
||||
}
|
||||
|
||||
void CInteropResource::SetFullDamage()
|
||||
{
|
||||
m_dirtyRects[0].left = 0;
|
||||
m_dirtyRects[0].top = 0;
|
||||
m_dirtyRects[0].right = m_format.Width;
|
||||
m_dirtyRects[0].bottom = m_format.Height;
|
||||
m_nbDirtyRects = 1;
|
||||
}
|
48
idd/LGIdd/CInteropResource.h
Normal file
48
idd/LGIdd/CInteropResource.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <wdf.h>
|
||||
#include <wrl.h>
|
||||
#include <memory>
|
||||
|
||||
#include "CD3D11Device.h"
|
||||
#include "CD3D12Device.h"
|
||||
#include "CD3D12CommandQueue.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
#define LG_MAX_DIRTY_RECTS 256
|
||||
|
||||
class CInteropResource
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<CD3D11Device> m_dx11Device;
|
||||
std::shared_ptr<CD3D12Device> m_dx12Device;
|
||||
|
||||
/* this value is likely released, it is only used to check if the texture supplied
|
||||
is different, do not rely on it pointing to valid memory */
|
||||
void * m_srcTex;
|
||||
|
||||
ComPtr<ID3D12Resource > m_d12Res;
|
||||
D3D11_TEXTURE2D_DESC m_format;
|
||||
ComPtr<ID3D11Fence > m_d11Fence;
|
||||
ComPtr<ID3D12Fence > m_d12Fence;
|
||||
UINT64 m_fenceValue;
|
||||
bool m_ready;
|
||||
|
||||
RECT m_dirtyRects[LG_MAX_DIRTY_RECTS];
|
||||
unsigned m_nbDirtyRects;
|
||||
|
||||
public:
|
||||
bool Init(std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device, ComPtr<ID3D11Texture2D> srcTex);
|
||||
void Reset();
|
||||
|
||||
bool IsReady() { return m_ready; }
|
||||
bool Compare(const ComPtr<ID3D11Texture2D>& srcTex);
|
||||
void Signal();
|
||||
void Sync(CD3D12CommandQueue& queue);
|
||||
void SetFullDamage();
|
||||
|
||||
const ComPtr<ID3D12Resource>& GetRes() { return m_d12Res; }
|
||||
const D3D11_TEXTURE2D_DESC& GetFormat() { return m_format; }
|
||||
};
|
47
idd/LGIdd/CInteropResourcePool.cpp
Normal file
47
idd/LGIdd/CInteropResourcePool.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "CInteropResourcePool.h"
|
||||
#include "Debug.h"
|
||||
|
||||
void CInteropResourcePool::Init(std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device)
|
||||
{
|
||||
Reset();
|
||||
m_dx11Device = dx11Device;
|
||||
m_dx12Device = dx12Device;
|
||||
}
|
||||
|
||||
void CInteropResourcePool::Reset()
|
||||
{
|
||||
for (unsigned i = 0; i < POOL_SIZE; ++i)
|
||||
m_pool[i].Reset();
|
||||
m_dx11Device.reset();
|
||||
m_dx12Device.reset();
|
||||
}
|
||||
|
||||
CInteropResource* CInteropResourcePool::Get(ComPtr<ID3D11Texture2D> srcTex)
|
||||
{
|
||||
CInteropResource * res;
|
||||
unsigned freeSlot = POOL_SIZE;
|
||||
for (unsigned i = 0; i < POOL_SIZE; ++i)
|
||||
{
|
||||
res = &m_pool[i];
|
||||
if (!res->IsReady())
|
||||
{
|
||||
freeSlot = min(freeSlot, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (res->Compare(srcTex))
|
||||
return res;
|
||||
}
|
||||
|
||||
if (freeSlot == POOL_SIZE)
|
||||
{
|
||||
DBGPRINT("Interop Resouce Pool Full");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
res = &m_pool[freeSlot];
|
||||
if (!res->Init(m_dx11Device, m_dx12Device, srcTex))
|
||||
return nullptr;
|
||||
|
||||
return res;
|
||||
}
|
26
idd/LGIdd/CInteropResourcePool.h
Normal file
26
idd/LGIdd/CInteropResourcePool.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <wdf.h>
|
||||
#include <wrl.h>
|
||||
#include <d3d11_4.h>
|
||||
#include "CInteropResource.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
#define POOL_SIZE 10
|
||||
|
||||
class CInteropResourcePool
|
||||
{
|
||||
private:
|
||||
CInteropResource m_pool[POOL_SIZE];
|
||||
|
||||
std::shared_ptr<CD3D11Device> m_dx11Device;
|
||||
std::shared_ptr<CD3D12Device> m_dx12Device;
|
||||
|
||||
public:
|
||||
void Init(std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device);
|
||||
void Reset();
|
||||
|
||||
CInteropResource* Get(ComPtr<ID3D11Texture2D> srcTex);
|
||||
};
|
@ -35,15 +35,18 @@
|
||||
#define UNLOCK_ST(st) UNLOCK((st).lock);
|
||||
|
||||
CSwapChainProcessor::CSwapChainProcessor(CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent) :
|
||||
std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device, HANDLE newFrameEvent) :
|
||||
m_devContext(devContext),
|
||||
m_hSwapChain(hSwapChain),
|
||||
m_device(device),
|
||||
m_dx11Device(dx11Device),
|
||||
m_dx12Device(dx12Device),
|
||||
m_newFrameEvent(newFrameEvent)
|
||||
{
|
||||
{
|
||||
m_resPool.Init(dx11Device, dx12Device);
|
||||
m_fbPool.Init(this);
|
||||
|
||||
m_terminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, 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()
|
||||
@ -54,12 +57,8 @@ CSwapChainProcessor::~CSwapChainProcessor()
|
||||
if (m_thread[1].Get())
|
||||
WaitForSingleObject(m_thread[1].Get(), INFINITE);
|
||||
|
||||
for(int i = 0; i < STAGING_TEXTURES; ++i)
|
||||
if (m_cpuTex[i].map.pData)
|
||||
{
|
||||
m_device->m_context->Unmap(m_cpuTex[i].tex.Get(), 0);
|
||||
m_cpuTex[i].map.pData = nullptr;
|
||||
}
|
||||
m_resPool.Reset();
|
||||
m_fbPool.Reset();
|
||||
}
|
||||
|
||||
DWORD CALLBACK CSwapChainProcessor::_SwapChainThread(LPVOID arg)
|
||||
@ -84,8 +83,8 @@ void CSwapChainProcessor::SwapChainThread()
|
||||
|
||||
void CSwapChainProcessor::SwapChainThreadCore()
|
||||
{
|
||||
Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
|
||||
HRESULT hr = m_device->m_device.As(&dxgiDevice);
|
||||
ComPtr<IDXGIDevice> dxgiDevice;
|
||||
HRESULT hr = m_dx11Device->GetDevice().As(&dxgiDevice);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT("Failed to get the dxgiDevice");
|
||||
@ -109,10 +108,7 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
||||
IDARG_IN_SWAPCHAINSETDEVICE setDevice = {};
|
||||
setDevice.pDevice = dxgiDevice.Get();
|
||||
|
||||
LOCK_CONTEXT();
|
||||
hr = IddCxSwapChainSetDevice(m_hSwapChain, &setDevice);
|
||||
UNLOCK_CONTEXT();
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT("IddCxSwapChainSetDevice Failed (%08x)", hr);
|
||||
@ -122,15 +118,11 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
||||
UINT lastFrameNumber = 0;
|
||||
for (;;)
|
||||
{
|
||||
ComPtr<IDXGIResource> acquiredBuffer;
|
||||
IDARG_OUT_RELEASEANDACQUIREBUFFER buffer = {};
|
||||
|
||||
LOCK_CONTEXT();
|
||||
hr = IddCxSwapChainReleaseAndAcquireBuffer(m_hSwapChain, &buffer);
|
||||
|
||||
if (hr == E_PENDING)
|
||||
{
|
||||
UNLOCK_CONTEXT();
|
||||
HANDLE waitHandles[] =
|
||||
{
|
||||
m_newFrameEvent,
|
||||
@ -152,22 +144,15 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
||||
if (buffer.MetaData.PresentationFrameNumber != lastFrameNumber)
|
||||
{
|
||||
lastFrameNumber = buffer.MetaData.PresentationFrameNumber;
|
||||
if (m_copyCount < STAGING_TEXTURES)
|
||||
{
|
||||
acquiredBuffer.Attach(buffer.MetaData.pSurface);
|
||||
SwapChainNewFrame(acquiredBuffer);
|
||||
acquiredBuffer.Reset();
|
||||
}
|
||||
SwapChainNewFrame(buffer.MetaData.pSurface);
|
||||
}
|
||||
|
||||
hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
|
||||
UNLOCK_CONTEXT();
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNLOCK_CONTEXT();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -175,119 +160,78 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
||||
|
||||
void CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
|
||||
if (FAILED(acquiredBuffer->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&texture)))
|
||||
ComPtr<ID3D11Texture2D> texture;
|
||||
HRESULT hr = acquiredBuffer.As(&texture);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DBGPRINT("Failed to obtain the ID3D11Texture2D from the acquiredBuffer");
|
||||
DBGPRINT_HR(hr, "Failed to obtain the ID3D11Texture2D from the acquiredBuffer");
|
||||
return;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture->GetDesc(&desc);
|
||||
|
||||
StagingTexture &st = m_cpuTex[m_texWIndex];
|
||||
if (st.map.pData)
|
||||
CInteropResource * srcRes = m_resPool.Get(texture);
|
||||
if (!srcRes)
|
||||
{
|
||||
m_device->m_context->Unmap(st.tex.Get(), 0);
|
||||
st.map.pData = nullptr;
|
||||
DBGPRINT("Failed to get a CInteropResource from the pool");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SetupStagingTexture(st, desc.Width, desc.Height, desc.Format))
|
||||
/**
|
||||
* Even though we have not performed any copy/draw operations we still need to
|
||||
* use a fence. Because we share this texture with DirectX12 it is able to
|
||||
* read from it before the desktop duplication API has finished updating it.
|
||||
*/
|
||||
srcRes->Signal();
|
||||
|
||||
//FIXME: handle dirty rects
|
||||
srcRes->SetFullDamage();
|
||||
|
||||
auto buffer = m_devContext->PrepareFrameBuffer(
|
||||
srcRes->GetFormat().Width,
|
||||
srcRes->GetFormat().Height,
|
||||
srcRes->GetFormat().Width * 4,
|
||||
srcRes->GetFormat().Format);
|
||||
|
||||
if (!buffer.mem)
|
||||
return;
|
||||
|
||||
m_device->m_context->CopyResource(st.tex.Get(), texture.Get());
|
||||
CFrameBufferResource * fbRes = m_fbPool.Get(buffer,
|
||||
((size_t)srcRes->GetFormat().Width * 4) * srcRes->GetFormat().Height);
|
||||
|
||||
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 (!fbRes)
|
||||
{
|
||||
if (WaitForSingleObject(m_terminateEvent.Get(), 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (!m_copyCount)
|
||||
{
|
||||
Sleep(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
StagingTexture & st = m_cpuTex[m_texRIndex];
|
||||
LOCK(st);
|
||||
|
||||
LOCK_CONTEXT();
|
||||
HRESULT status = m_device->m_context->Map(st.tex.Get(), 0, D3D11_MAP_READ,
|
||||
D3D11_MAP_FLAG_DO_NOT_WAIT, &st.map);
|
||||
UNLOCK_CONTEXT();
|
||||
|
||||
if (FAILED(status))
|
||||
{
|
||||
UNLOCK(st);
|
||||
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(st.width, st.height, st.map.RowPitch, st.format, st.map.pData);
|
||||
InterlockedAdd(&m_copyCount, -1);
|
||||
m_lastIndex = m_texRIndex;
|
||||
if (++m_texRIndex == STAGING_TEXTURES)
|
||||
m_texRIndex = 0;
|
||||
|
||||
UNLOCK(st);
|
||||
DBGPRINT("Failed to get a CFrameBufferResource from the pool");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION srcLoc = {};
|
||||
srcLoc.pResource = srcRes->GetRes().Get();
|
||||
srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
srcLoc.SubresourceIndex = 0;
|
||||
|
||||
bool CSwapChainProcessor::SetupStagingTexture(StagingTexture & st, int width, int height, DXGI_FORMAT format)
|
||||
{
|
||||
if (st.width == width && st.height == height && st.format == format)
|
||||
return true;
|
||||
D3D12_TEXTURE_COPY_LOCATION dstLoc = {};
|
||||
dstLoc.pResource = fbRes->Get().Get();
|
||||
dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
dstLoc.PlacedFootprint.Offset = 0;
|
||||
dstLoc.PlacedFootprint.Footprint.Format = srcRes->GetFormat().Format;
|
||||
dstLoc.PlacedFootprint.Footprint.Width = srcRes->GetFormat().Width;
|
||||
dstLoc.PlacedFootprint.Footprint.Height = srcRes->GetFormat().Height;
|
||||
dstLoc.PlacedFootprint.Footprint.Depth = 1;
|
||||
dstLoc.PlacedFootprint.Footprint.RowPitch = srcRes->GetFormat().Width * 4; //FIXME
|
||||
|
||||
st.tex.Reset();
|
||||
st.width = width;
|
||||
st.height = height;
|
||||
st.format = format;
|
||||
srcRes->Sync(m_dx12Device->GetCopyQueue());
|
||||
m_dx12Device->GetCopyQueue().GetGfxList()->CopyTextureRegion(
|
||||
&dstLoc, 0, 0, 0, &srcLoc, NULL);
|
||||
|
||||
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;
|
||||
m_dx12Device->GetCopyQueue().Execute();
|
||||
m_dx12Device->GetCopyQueue().Wait();
|
||||
m_dx12Device->GetCopyQueue().Reset();
|
||||
|
||||
if (FAILED(m_device->m_device->CreateTexture2D(&desc, nullptr, &st.tex)))
|
||||
{
|
||||
DBGPRINT("Failed to create staging texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
m_devContext->FinalizeFrameBuffer();
|
||||
}
|
||||
|
||||
void CSwapChainProcessor::ResendLastFrame()
|
||||
{
|
||||
/*
|
||||
LOCK_CONTEXT()
|
||||
StagingTexture & st = m_cpuTex[m_lastIndex];
|
||||
LOCK_ST(st);
|
||||
@ -301,4 +245,5 @@ void CSwapChainProcessor::ResendLastFrame()
|
||||
|
||||
m_devContext->SendFrame(st.width, st.height, st.map.RowPitch, st.format, st.map.pData);
|
||||
UNLOCK_ST(st);
|
||||
*/
|
||||
}
|
@ -20,8 +20,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Direct3DDevice.h"
|
||||
#include "CD3D11Device.h"
|
||||
#include "CD3D12Device.h"
|
||||
#include "CIndirectDeviceContext.h"
|
||||
#include "CInteropResourcePool.h"
|
||||
#include "CFrameBufferPool.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <wrl.h>
|
||||
@ -37,45 +40,29 @@ class CSwapChainProcessor
|
||||
private:
|
||||
CIndirectDeviceContext * m_devContext;
|
||||
IDDCX_SWAPCHAIN m_hSwapChain;
|
||||
std::shared_ptr<Direct3DDevice> m_device;
|
||||
std::shared_ptr<CD3D11Device> m_dx11Device;
|
||||
std::shared_ptr<CD3D12Device> m_dx12Device;
|
||||
HANDLE m_newFrameEvent;
|
||||
|
||||
CInteropResourcePool m_resPool;
|
||||
CFrameBufferPool m_fbPool;
|
||||
|
||||
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread[2];
|
||||
Wrappers::Event m_terminateEvent;
|
||||
|
||||
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
||||
static DWORD CALLBACK _FrameThread(LPVOID arg);
|
||||
|
||||
|
||||
void SwapChainThread();
|
||||
void SwapChainThreadCore();
|
||||
void SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer);
|
||||
|
||||
void FrameThread();
|
||||
|
||||
struct StagingTexture
|
||||
{
|
||||
volatile LONG lock = 0;
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> tex;
|
||||
D3D11_MAPPED_SUBRESOURCE map = {};
|
||||
};
|
||||
|
||||
StagingTexture m_cpuTex[STAGING_TEXTURES] = {};
|
||||
volatile LONG m_copyCount = 0;
|
||||
volatile LONG m_contextLock = 0;
|
||||
int m_texRIndex = 0;
|
||||
int m_texWIndex = 0;
|
||||
int m_lastIndex = 0;
|
||||
|
||||
bool SetupStagingTexture(StagingTexture & st, int width, int height, DXGI_FORMAT format);
|
||||
|
||||
public:
|
||||
CSwapChainProcessor(CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent);
|
||||
std::shared_ptr<CD3D11Device> dx11Device, std::shared_ptr<CD3D12Device> dx12Device, HANDLE newFrameEvent);
|
||||
~CSwapChainProcessor();
|
||||
|
||||
CIndirectDeviceContext * GetDevice() { return m_devContext; }
|
||||
std::shared_ptr<CD3D12Device> GetD3D12Device() { return m_dx12Device; }
|
||||
|
||||
void ResendLastFrame();
|
||||
};
|
@ -22,18 +22,21 @@
|
||||
#include <malloc.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
/* credit: https://stackoverflow.com/questions/29049686/is-there-a-better-way-to-pass-formatted-output-to-outputdebugstring */
|
||||
VOID _DBGPRINT(PCSTR kwszFunction, INT iLineNumber, LPCSTR kszDebugFormatString, ...) \
|
||||
VOID _DBGPRINT(PCSTR kwszFunction, INT iLineNumber, LPCSTR kszDebugFormatString, ...)
|
||||
{
|
||||
INT cbFormatString = 0;
|
||||
va_list args;
|
||||
PCHAR szDebugString = NULL;
|
||||
size_t st_Offset = 0;
|
||||
size_t stOffset = 0;
|
||||
|
||||
va_start(args, kszDebugFormatString);
|
||||
|
||||
cbFormatString = _scprintf("[%s:%d] ", kwszFunction, iLineNumber) * sizeof(CHAR);
|
||||
cbFormatString += _vscprintf(kszDebugFormatString, args) * sizeof(CHAR) + 2;
|
||||
cbFormatString = _scprintf("[%s:%d] ", kwszFunction, iLineNumber);
|
||||
cbFormatString += _vscprintf(kszDebugFormatString, args);
|
||||
cbFormatString += 2;
|
||||
|
||||
/* Depending on the size of the format string, allocate space on the stack or the heap. */
|
||||
szDebugString = (PCHAR)_malloca(cbFormatString);
|
||||
@ -42,11 +45,64 @@ VOID _DBGPRINT(PCSTR kwszFunction, INT iLineNumber, LPCSTR kszDebugFormatString,
|
||||
|
||||
/* Populate the buffer with the contents of the format string. */
|
||||
StringCbPrintfA(szDebugString, cbFormatString, "[%s:%d] ", kwszFunction, iLineNumber);
|
||||
StringCbLengthA(szDebugString, cbFormatString, &st_Offset);
|
||||
StringCbVPrintfA(&szDebugString[st_Offset / sizeof(CHAR)], cbFormatString - st_Offset, kszDebugFormatString, args);
|
||||
StringCbLengthA(szDebugString, cbFormatString, &stOffset);
|
||||
StringCbVPrintfA(&szDebugString[stOffset], cbFormatString - stOffset, kszDebugFormatString, args);
|
||||
|
||||
OutputDebugStringA(szDebugString);
|
||||
|
||||
_freea(szDebugString);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
VOID _DBGPRINT_HR(PCSTR kwszFunction, INT iLineNumber, LPCSTR kszDebugFormatString, HRESULT status, ...)
|
||||
{
|
||||
char * buffer;
|
||||
if (!FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
status,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(char*)&buffer,
|
||||
1024,
|
||||
NULL
|
||||
))
|
||||
{
|
||||
DBGPRINT("FormatMessage failed with code 0x%08x", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
INT cbFormatString = 0;
|
||||
va_list args;
|
||||
PCHAR szDebugString = NULL;
|
||||
size_t stOffset = 0;
|
||||
|
||||
va_start(args, kszDebugFormatString);
|
||||
|
||||
cbFormatString = _scprintf("[%s:%d] ", kwszFunction, iLineNumber);
|
||||
cbFormatString += _vscprintf(kszDebugFormatString, args);
|
||||
cbFormatString += 2 + 4 + (int)strlen(buffer);
|
||||
|
||||
/* Depending on the size of the format string, allocate space on the stack or the heap. */
|
||||
szDebugString = (PCHAR)_malloca(cbFormatString);
|
||||
if (!szDebugString)
|
||||
{
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Populate the buffer with the contents of the format string. */
|
||||
StringCbPrintfA(szDebugString, cbFormatString, "[%s:%d] ", kwszFunction, iLineNumber);
|
||||
StringCbLengthA(szDebugString, cbFormatString, &stOffset);
|
||||
StringCbVPrintfA(&szDebugString[stOffset], cbFormatString - stOffset, kszDebugFormatString, args);
|
||||
|
||||
/* append the formatted error */
|
||||
StringCbLengthA(szDebugString, cbFormatString, &stOffset);
|
||||
StringCbPrintfA(&szDebugString[stOffset], cbFormatString - stOffset, " (%s)", buffer);
|
||||
|
||||
OutputDebugStringA(szDebugString);
|
||||
|
||||
_freea(szDebugString);
|
||||
va_end(args);
|
||||
|
||||
LocalFree(buffer);
|
||||
}
|
@ -25,4 +25,8 @@
|
||||
|
||||
VOID _DBGPRINT(PCSTR kszFunction, INT iLineNumber, LPCSTR kszDebugFormatString, ...);
|
||||
#define DBGPRINT(kszDebugFormatString, ...) \
|
||||
_DBGPRINT(__FUNCTION__, __LINE__, kszDebugFormatString, __VA_ARGS__)
|
||||
_DBGPRINT(__FUNCTION__, __LINE__, kszDebugFormatString "\n", __VA_ARGS__)
|
||||
|
||||
VOID _DBGPRINT_HR(PCSTR kwszFunction, INT iLineNumber, LPCSTR kszDebugFormatString, HRESULT status, ...);
|
||||
#define DBGPRINT_HR(status, kszDebugFormatString, ...) \
|
||||
_DBGPRINT_HR(__FUNCTION__, __LINE__, kszDebugFormatString "\n", status, __VA_ARGS__)
|
||||
|
@ -140,7 +140,8 @@ NTSTATUS LGIddMonitorQueryTargetModes(IDDCX_MONITOR monitor, const IDARG_IN_QUER
|
||||
NTSTATUS LGIddMonitorAssignSwapChain(IDDCX_MONITOR monitor, const IDARG_IN_SETSWAPCHAIN* inArgs)
|
||||
{
|
||||
auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
|
||||
wrapper->context->AssignSwapChain(inArgs->hSwapChain, inArgs->RenderAdapterLuid, inArgs->hNextSurfaceAvailable);
|
||||
wrapper->context->AssignSwapChain(
|
||||
inArgs->hSwapChain, inArgs->RenderAdapterLuid, inArgs->hNextSurfaceAvailable);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -46,16 +46,19 @@ NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING Reg
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
|
||||
#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0
|
||||
WPP_CLEANUP();
|
||||
#else
|
||||
WPP_CLEANUP(DriverObject);
|
||||
#endif
|
||||
return status;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
|
||||
return status;
|
||||
|
||||
fail:
|
||||
#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0
|
||||
WPP_CLEANUP();
|
||||
#else
|
||||
WPP_CLEANUP(DriverObject);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS LGIddEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
|
||||
|
@ -38,24 +38,36 @@
|
||||
<None Include="cpp.hint" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CD3D12CommandQueue.cpp" />
|
||||
<ClCompile Include="CFrameBufferPool.cpp" />
|
||||
<ClCompile Include="CFrameBufferResource.cpp" />
|
||||
<ClCompile Include="CIndirectDeviceContext.cpp" />
|
||||
<ClCompile Include="CIndirectMonitorContext.cpp" />
|
||||
<ClCompile Include="CInteropResourcePool.cpp" />
|
||||
<ClCompile Include="CInteropResource.cpp" />
|
||||
<ClCompile Include="CIVSHMEM.cpp" />
|
||||
<ClCompile Include="CPlatformInfo.cpp" />
|
||||
<ClCompile Include="CSwapChainProcessor.cpp" />
|
||||
<ClCompile Include="CD3D12Device.cpp" />
|
||||
<ClCompile Include="Debug.cpp" />
|
||||
<ClCompile Include="Device.cpp" />
|
||||
<ClCompile Include="Direct3DDevice.cpp" />
|
||||
<ClCompile Include="CD3D11Device.cpp" />
|
||||
<ClCompile Include="Driver.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CD3D12CommandQueue.h" />
|
||||
<ClInclude Include="CFrameBufferPool.h" />
|
||||
<ClInclude Include="CFrameBufferResource.h" />
|
||||
<ClInclude Include="CIndirectMonitorContext.h" />
|
||||
<ClInclude Include="CInteropResourcePool.h" />
|
||||
<ClInclude Include="CInteropResource.h" />
|
||||
<ClInclude Include="CIVSHMEM.h" />
|
||||
<ClInclude Include="CPlatformInfo.h" />
|
||||
<ClInclude Include="CSwapChainProcessor.h" />
|
||||
<ClInclude Include="CD3D12Device.h" />
|
||||
<ClInclude Include="Debug.h" />
|
||||
<ClInclude Include="Device.h" />
|
||||
<ClInclude Include="Direct3DDevice.h" />
|
||||
<ClInclude Include="CD3D11Device.h" />
|
||||
<ClInclude Include="Driver.h" />
|
||||
<ClInclude Include="CIndirectDeviceContext.h" />
|
||||
<ClInclude Include="Public.h" />
|
||||
@ -257,7 +269,7 @@
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;$(ProjectDir)..\..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib;d3d12.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
||||
@ -272,7 +284,7 @@
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;$(ProjectDir)..\..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib;d3d12.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
||||
|
@ -48,9 +48,6 @@
|
||||
<ClInclude Include="CSwapChainProcessor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Direct3DDevice.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CIVSHMEM.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -60,6 +57,27 @@
|
||||
<ClInclude Include="CPlatformInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CD3D12CommandQueue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CInteropResourcePool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CInteropResource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CD3D12Device.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CD3D11Device.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CFrameBufferResource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CFrameBufferPool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Device.cpp">
|
||||
@ -77,9 +95,6 @@
|
||||
<ClCompile Include="CSwapChainProcessor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Direct3DDevice.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CIVSHMEM.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -89,5 +104,26 @@
|
||||
<ClCompile Include="CPlatformInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CD3D12CommandQueue.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CInteropResourcePool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CInteropResource.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CD3D12Device.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CD3D11Device.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CFrameBufferResource.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CFrameBufferPool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1 +1 @@
|
||||
Subproject commit eddecb588839b2b88ac3a77e0a064daa96aab541
|
||||
Subproject commit f8482c14aae84edf5fc0f3a8c5d3ade0c29df219
|
Loading…
x
Reference in New Issue
Block a user