mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-05-07 15:11:19 +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
|
* 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));
|
HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&m_factory));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@ -30,17 +31,36 @@ HRESULT Direct3DDevice::Init()
|
|||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return 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(
|
hr = D3D11CreateDevice(
|
||||||
m_adapter.Get(),
|
m_adapter.Get(),
|
||||||
D3D_DRIVER_TYPE_UNKNOWN,
|
D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
nullptr,
|
nullptr,
|
||||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG,
|
||||||
nullptr,
|
featureLevels,
|
||||||
0,
|
ARRAYSIZE(featureLevels),
|
||||||
D3D11_SDK_VERSION,
|
D3D11_SDK_VERSION,
|
||||||
&m_device,
|
&device,
|
||||||
nullptr,
|
&featureLevel,
|
||||||
&m_context);
|
&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))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
@ -26,21 +26,29 @@
|
|||||||
#include <dxgi1_5.h>
|
#include <dxgi1_5.h>
|
||||||
#include <d3d11_4.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) {};
|
m_adapterLuid(adapterLuid) {};
|
||||||
|
|
||||||
Direct3DDevice()
|
CD3D11Device()
|
||||||
{
|
{
|
||||||
m_adapterLuid = LUID{};
|
m_adapterLuid = LUID{};
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Init();
|
HRESULT Init();
|
||||||
|
|
||||||
LUID m_adapterLuid;
|
ComPtr<ID3D11Device5> GetDevice() { return m_device; }
|
||||||
Microsoft::WRL::ComPtr<IDXGIFactory5 > m_factory;
|
|
||||||
Microsoft::WRL::ComPtr<IDXGIAdapter1 > m_adapter;
|
ComPtr<ID3D11DeviceContext4> GetContext() { return m_context; }
|
||||||
Microsoft::WRL::ComPtr<ID3D11Device > m_device;
|
|
||||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext> 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 bus = it->busAddr >> 32;
|
||||||
DWORD addr = it->busAddr & 0xFFFFFFFF;
|
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);
|
i, i == shmDevice ? '*' : ' ', bus, addr >> 16, addr & 0xFFFF);
|
||||||
|
|
||||||
if (i == shmDevice)
|
if (i == shmDevice)
|
||||||
|
@ -40,29 +40,9 @@ static const struct LGMPQueueConfig POINTER_QUEUE_CONFIG =
|
|||||||
1000 //subTimeout
|
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()
|
void CIndirectDeviceContext::InitAdapter()
|
||||||
{
|
{
|
||||||
if (!SetupLGMP())
|
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IDDCX_ADAPTER_CAPS caps = {};
|
IDDCX_ADAPTER_CAPS caps = {};
|
||||||
@ -193,10 +173,14 @@ void CIndirectDeviceContext::FinishInit(UINT connectorIndex)
|
|||||||
status = IddCxMonitorArrival(m_monitor, &out);
|
status = IddCxMonitorArrival(m_monitor, &out);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CIndirectDeviceContext::SetupLGMP()
|
bool CIndirectDeviceContext::SetupLGMP(size_t alignSize)
|
||||||
{
|
{
|
||||||
if (!m_ivshmem.Init() || !m_ivshmem.Open())
|
// this may get called multiple times as we need to delay calling it until
|
||||||
return false;
|
// we can determine the required alignment from the GPU in use
|
||||||
|
if (m_lgmp)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
m_alignSize = alignSize;
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
{
|
{
|
||||||
@ -310,13 +294,13 @@ bool CIndirectDeviceContext::SetupLGMP()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_maxFrameSize = lgmpHostMemAvail(m_lgmp);
|
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;
|
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)
|
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||||
if ((status = lgmpHostMemAllocAligned(m_lgmp, (uint32_t)m_maxFrameSize,
|
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));
|
DBGPRINT("lgmpHostMemAllocAligned Failed (Frame): %s", lgmpStatusString(status));
|
||||||
return false;
|
return false;
|
||||||
@ -353,6 +337,26 @@ bool CIndirectDeviceContext::SetupLGMP()
|
|||||||
return true;
|
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()
|
void CIndirectDeviceContext::LGMPTimer()
|
||||||
{
|
{
|
||||||
LGMP_STATUS status;
|
LGMP_STATUS status;
|
||||||
@ -399,10 +403,22 @@ void CIndirectDeviceContext::LGMPTimer()
|
|||||||
ResendCursor();
|
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)
|
if (!m_lgmp || !m_frameQueue)
|
||||||
return;
|
return result;
|
||||||
|
|
||||||
if (m_width != width || m_height != height || m_pitch != pitch || m_format != format)
|
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;
|
++m_formatVer;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (lgmpHostQueuePending(m_frameQueue) == LGMP_Q_FRAME_LEN)
|
|
||||||
Sleep(0);
|
|
||||||
|
|
||||||
if (++m_frameIndex == LGMP_Q_FRAME_LEN)
|
if (++m_frameIndex == LGMP_Q_FRAME_LEN)
|
||||||
m_frameIndex = 0;
|
m_frameIndex = 0;
|
||||||
|
|
||||||
KVMFRFrame * fi = (KVMFRFrame *)lgmpHostMemPtr(m_frameMemory[m_frameIndex]);
|
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;
|
int bpp = 4;
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
@ -434,19 +452,9 @@ void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FO
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
DBGPRINT("Unsuppoted DXGI format");
|
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->formatVer = m_formatVer;
|
||||||
fi->frameSerial = m_frameSerial++;
|
fi->frameSerial = m_frameSerial++;
|
||||||
fi->screenWidth = width;
|
fi->screenWidth = width;
|
||||||
@ -457,18 +465,30 @@ void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FO
|
|||||||
fi->frameHeight = height;
|
fi->frameHeight = height;
|
||||||
fi->stride = width * bpp;
|
fi->stride = width * bpp;
|
||||||
fi->pitch = pitch;
|
fi->pitch = pitch;
|
||||||
fi->offset = (uint32_t)(CPlatformInfo::GetPageSize() - sizeof(FrameBuffer));
|
fi->offset = (uint32_t)(m_alignSize - sizeof(FrameBuffer));
|
||||||
fi->flags = 0;
|
fi->flags = 0;
|
||||||
fi->rotation = FRAME_ROT_0;
|
fi->rotation = FRAME_ROT_0;
|
||||||
|
|
||||||
fi->damageRectsCount = 0;
|
fi->damageRectsCount = 0;
|
||||||
|
|
||||||
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)fi) + fi->offset);
|
FrameBuffer* fb = (FrameBuffer*)(((uint8_t*)fi) + fi->offset);
|
||||||
fb->wp = 0;
|
fb->wp = 0;
|
||||||
|
|
||||||
lgmpHostQueuePost(m_frameQueue, 0, m_frameMemory[m_frameIndex]);
|
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)
|
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)
|
if (info.CursorShapeInfo.CursorType != IDDCX_CURSOR_SHAPE_TYPE_UNINITIALIZED)
|
||||||
{
|
{
|
||||||
memcpy(cursor + 1, data,
|
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->hx = (int8_t )info.CursorShapeInfo.XHot;
|
||||||
cursor->hy = (int8_t )info.CursorShapeInfo.YHot;
|
cursor->hy = (int8_t )info.CursorShapeInfo.YHot;
|
||||||
|
@ -56,6 +56,7 @@ private:
|
|||||||
bool m_cursorVisible = false;
|
bool m_cursorVisible = false;
|
||||||
int m_cursorX = 0, m_cursorY = 0;
|
int m_cursorX = 0, m_cursorY = 0;
|
||||||
|
|
||||||
|
size_t m_alignSize = 0;
|
||||||
size_t m_maxFrameSize = 0;
|
size_t m_maxFrameSize = 0;
|
||||||
int m_frameIndex = 0;
|
int m_frameIndex = 0;
|
||||||
uint32_t m_formatVer = 0;
|
uint32_t m_formatVer = 0;
|
||||||
@ -67,7 +68,7 @@ private:
|
|||||||
int m_pitch = 0;
|
int m_pitch = 0;
|
||||||
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
|
||||||
bool SetupLGMP();
|
void DeInitLGMP();
|
||||||
void LGMPTimer();
|
void LGMPTimer();
|
||||||
void ResendCursor();
|
void ResendCursor();
|
||||||
|
|
||||||
@ -75,14 +76,29 @@ public:
|
|||||||
CIndirectDeviceContext(_In_ WDFDEVICE wdfDevice) :
|
CIndirectDeviceContext(_In_ WDFDEVICE wdfDevice) :
|
||||||
m_wdfDevice(wdfDevice) {};
|
m_wdfDevice(wdfDevice) {};
|
||||||
|
|
||||||
virtual ~CIndirectDeviceContext();
|
virtual ~CIndirectDeviceContext() { DeInitLGMP(); }
|
||||||
|
|
||||||
|
bool SetupLGMP(size_t alignSize);
|
||||||
|
|
||||||
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);
|
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);
|
void SendCursor(const IDARG_OUT_QUERY_HWCURSOR & info, const BYTE * data);
|
||||||
|
|
||||||
|
CIVSHMEM &GetIVSHMEM() { return m_ivshmem; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CIndirectDeviceContextWrapper
|
struct CIndirectDeviceContextWrapper
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CIndirectMonitorContext.h"
|
#include "CIndirectMonitorContext.h"
|
||||||
#include "Direct3DDevice.h"
|
#include "CPlatformInfo.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
|
|
||||||
CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device) :
|
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_terminateEvent .Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||||
m_cursorDataEvent.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];
|
m_shapeBuffer = new BYTE[512 * 512 * 4];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,14 +41,27 @@ CIndirectMonitorContext::~CIndirectMonitorContext()
|
|||||||
void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent)
|
void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent)
|
||||||
{
|
{
|
||||||
m_swapChain.reset();
|
m_swapChain.reset();
|
||||||
auto device = std::make_shared<Direct3DDevice>(renderAdapter);
|
m_dx11Device = std::make_shared<CD3D11Device>(renderAdapter);
|
||||||
if (FAILED(device->Init()))
|
if (FAILED(m_dx11Device->Init()))
|
||||||
{
|
{
|
||||||
WdfObjectDelete(swapChain);
|
WdfObjectDelete(swapChain);
|
||||||
return;
|
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 = {};
|
IDARG_IN_SETUP_HWCURSOR c = {};
|
||||||
c.CursorInfo.Size = sizeof(c.CursorInfo);
|
c.CursorInfo.Size = sizeof(c.CursorInfo);
|
||||||
@ -60,12 +72,21 @@ void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID re
|
|||||||
c.hNewCursorDataAvailable = m_cursorDataEvent.Get();
|
c.hNewCursorDataAvailable = m_cursorDataEvent.Get();
|
||||||
NTSTATUS status = IddCxMonitorSetupHardwareCursor(m_monitor, &c);
|
NTSTATUS status = IddCxMonitorSetupHardwareCursor(m_monitor, &c);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
WdfObjectDelete(swapChain);
|
||||||
DBGPRINT("IddCxMonitorSetupHardwareCursor Failed: %08x", status);
|
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()
|
void CIndirectMonitorContext::UnassignSwapChain()
|
||||||
{
|
{
|
||||||
m_swapChain.reset();
|
m_swapChain.reset();
|
||||||
|
m_dx11Device.reset();
|
||||||
|
m_dx12Device.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD CALLBACK CIndirectMonitorContext::_CursorThread(LPVOID arg)
|
DWORD CALLBACK CIndirectMonitorContext::_CursorThread(LPVOID arg)
|
||||||
|
@ -34,6 +34,10 @@ class CIndirectMonitorContext
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
IDDCX_MONITOR m_monitor;
|
IDDCX_MONITOR m_monitor;
|
||||||
|
|
||||||
|
std::shared_ptr<CD3D11Device> m_dx11Device;
|
||||||
|
std::shared_ptr<CD3D12Device> m_dx12Device;
|
||||||
|
|
||||||
CIndirectDeviceContext * m_devContext;
|
CIndirectDeviceContext * m_devContext;
|
||||||
std::unique_ptr<CSwapChainProcessor> m_swapChain;
|
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);
|
#define UNLOCK_ST(st) UNLOCK((st).lock);
|
||||||
|
|
||||||
CSwapChainProcessor::CSwapChainProcessor(CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
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_devContext(devContext),
|
||||||
m_hSwapChain(hSwapChain),
|
m_hSwapChain(hSwapChain),
|
||||||
m_device(device),
|
m_dx11Device(dx11Device),
|
||||||
|
m_dx12Device(dx12Device),
|
||||||
m_newFrameEvent(newFrameEvent)
|
m_newFrameEvent(newFrameEvent)
|
||||||
{
|
{
|
||||||
|
m_resPool.Init(dx11Device, dx12Device);
|
||||||
|
m_fbPool.Init(this);
|
||||||
|
|
||||||
m_terminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
m_terminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||||
m_thread[0].Attach(CreateThread(nullptr, 0, _SwapChainThread, 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()
|
||||||
@ -54,12 +57,8 @@ CSwapChainProcessor::~CSwapChainProcessor()
|
|||||||
if (m_thread[1].Get())
|
if (m_thread[1].Get())
|
||||||
WaitForSingleObject(m_thread[1].Get(), INFINITE);
|
WaitForSingleObject(m_thread[1].Get(), INFINITE);
|
||||||
|
|
||||||
for(int i = 0; i < STAGING_TEXTURES; ++i)
|
m_resPool.Reset();
|
||||||
if (m_cpuTex[i].map.pData)
|
m_fbPool.Reset();
|
||||||
{
|
|
||||||
m_device->m_context->Unmap(m_cpuTex[i].tex.Get(), 0);
|
|
||||||
m_cpuTex[i].map.pData = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD CALLBACK CSwapChainProcessor::_SwapChainThread(LPVOID arg)
|
DWORD CALLBACK CSwapChainProcessor::_SwapChainThread(LPVOID arg)
|
||||||
@ -84,8 +83,8 @@ void CSwapChainProcessor::SwapChainThread()
|
|||||||
|
|
||||||
void CSwapChainProcessor::SwapChainThreadCore()
|
void CSwapChainProcessor::SwapChainThreadCore()
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
|
ComPtr<IDXGIDevice> dxgiDevice;
|
||||||
HRESULT hr = m_device->m_device.As(&dxgiDevice);
|
HRESULT hr = m_dx11Device->GetDevice().As(&dxgiDevice);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
DBGPRINT("Failed to get the dxgiDevice");
|
DBGPRINT("Failed to get the dxgiDevice");
|
||||||
@ -109,10 +108,7 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
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);
|
||||||
UNLOCK_CONTEXT();
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
DBGPRINT("IddCxSwapChainSetDevice Failed (%08x)", hr);
|
DBGPRINT("IddCxSwapChainSetDevice Failed (%08x)", hr);
|
||||||
@ -122,15 +118,11 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
UINT lastFrameNumber = 0;
|
UINT lastFrameNumber = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
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,
|
||||||
@ -152,22 +144,15 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
if (buffer.MetaData.PresentationFrameNumber != lastFrameNumber)
|
if (buffer.MetaData.PresentationFrameNumber != lastFrameNumber)
|
||||||
{
|
{
|
||||||
lastFrameNumber = buffer.MetaData.PresentationFrameNumber;
|
lastFrameNumber = buffer.MetaData.PresentationFrameNumber;
|
||||||
if (m_copyCount < STAGING_TEXTURES)
|
SwapChainNewFrame(buffer.MetaData.pSurface);
|
||||||
{
|
|
||||||
acquiredBuffer.Attach(buffer.MetaData.pSurface);
|
|
||||||
SwapChainNewFrame(acquiredBuffer);
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,119 +160,78 @@ void CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
|
|
||||||
void CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer)
|
void CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer)
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
|
ComPtr<ID3D11Texture2D> texture;
|
||||||
if (FAILED(acquiredBuffer->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D11_TEXTURE2D_DESC desc;
|
CInteropResource * srcRes = m_resPool.Get(texture);
|
||||||
texture->GetDesc(&desc);
|
if (!srcRes)
|
||||||
|
|
||||||
StagingTexture &st = m_cpuTex[m_texWIndex];
|
|
||||||
if (st.map.pData)
|
|
||||||
{
|
{
|
||||||
m_device->m_context->Unmap(st.tex.Get(), 0);
|
DBGPRINT("Failed to get a CInteropResource from the pool");
|
||||||
st.map.pData = nullptr;
|
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;
|
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 (!fbRes)
|
||||||
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)
|
DBGPRINT("Failed to get a CFrameBufferResource from the pool");
|
||||||
break;
|
return;
|
||||||
|
|
||||||
if (!m_copyCount)
|
|
||||||
{
|
|
||||||
Sleep(0);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StagingTexture & st = m_cpuTex[m_texRIndex];
|
D3D12_TEXTURE_COPY_LOCATION srcLoc = {};
|
||||||
LOCK(st);
|
srcLoc.pResource = srcRes->GetRes().Get();
|
||||||
|
srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
|
srcLoc.SubresourceIndex = 0;
|
||||||
|
|
||||||
LOCK_CONTEXT();
|
D3D12_TEXTURE_COPY_LOCATION dstLoc = {};
|
||||||
HRESULT status = m_device->m_context->Map(st.tex.Get(), 0, D3D11_MAP_READ,
|
dstLoc.pResource = fbRes->Get().Get();
|
||||||
D3D11_MAP_FLAG_DO_NOT_WAIT, &st.map);
|
dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||||
UNLOCK_CONTEXT();
|
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
|
||||||
|
|
||||||
if (FAILED(status))
|
srcRes->Sync(m_dx12Device->GetCopyQueue());
|
||||||
{
|
m_dx12Device->GetCopyQueue().GetGfxList()->CopyTextureRegion(
|
||||||
UNLOCK(st);
|
&dstLoc, 0, 0, 0, &srcLoc, NULL);
|
||||||
if (status == DXGI_ERROR_WAS_STILL_DRAWING)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DBGPRINT("Failed to map staging texture");
|
m_dx12Device->GetCopyQueue().Execute();
|
||||||
|
m_dx12Device->GetCopyQueue().Wait();
|
||||||
|
m_dx12Device->GetCopyQueue().Reset();
|
||||||
|
|
||||||
InterlockedAdd(&m_copyCount, -1);
|
m_devContext->FinalizeFrameBuffer();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSwapChainProcessor::SetupStagingTexture(StagingTexture & st, int width, int height, DXGI_FORMAT format)
|
|
||||||
{
|
|
||||||
if (st.width == width && st.height == height && st.format == format)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
st.tex.Reset();
|
|
||||||
st.width = width;
|
|
||||||
st.height = height;
|
|
||||||
st.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, &st.tex)))
|
|
||||||
{
|
|
||||||
DBGPRINT("Failed to create staging texture");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSwapChainProcessor::ResendLastFrame()
|
void CSwapChainProcessor::ResendLastFrame()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
LOCK_CONTEXT()
|
LOCK_CONTEXT()
|
||||||
StagingTexture & st = m_cpuTex[m_lastIndex];
|
StagingTexture & st = m_cpuTex[m_lastIndex];
|
||||||
LOCK_ST(st);
|
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);
|
m_devContext->SendFrame(st.width, st.height, st.map.RowPitch, st.format, st.map.pData);
|
||||||
UNLOCK_ST(st);
|
UNLOCK_ST(st);
|
||||||
|
*/
|
||||||
}
|
}
|
@ -20,8 +20,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Direct3DDevice.h"
|
#include "CD3D11Device.h"
|
||||||
|
#include "CD3D12Device.h"
|
||||||
#include "CIndirectDeviceContext.h"
|
#include "CIndirectDeviceContext.h"
|
||||||
|
#include "CInteropResourcePool.h"
|
||||||
|
#include "CFrameBufferPool.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
@ -37,45 +40,29 @@ class CSwapChainProcessor
|
|||||||
private:
|
private:
|
||||||
CIndirectDeviceContext * m_devContext;
|
CIndirectDeviceContext * m_devContext;
|
||||||
IDDCX_SWAPCHAIN m_hSwapChain;
|
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;
|
HANDLE m_newFrameEvent;
|
||||||
|
|
||||||
|
CInteropResourcePool m_resPool;
|
||||||
|
CFrameBufferPool m_fbPool;
|
||||||
|
|
||||||
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread[2];
|
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread[2];
|
||||||
Wrappers::Event m_terminateEvent;
|
Wrappers::Event m_terminateEvent;
|
||||||
|
|
||||||
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
||||||
static DWORD CALLBACK _FrameThread(LPVOID arg);
|
|
||||||
|
|
||||||
void SwapChainThread();
|
void SwapChainThread();
|
||||||
void SwapChainThreadCore();
|
void SwapChainThreadCore();
|
||||||
void SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer);
|
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:
|
public:
|
||||||
CSwapChainProcessor(CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain,
|
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();
|
~CSwapChainProcessor();
|
||||||
|
|
||||||
|
CIndirectDeviceContext * GetDevice() { return m_devContext; }
|
||||||
|
std::shared_ptr<CD3D12Device> GetD3D12Device() { return m_dx12Device; }
|
||||||
|
|
||||||
void ResendLastFrame();
|
void ResendLastFrame();
|
||||||
};
|
};
|
@ -22,18 +22,21 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
|
||||||
|
#include "Debug.h"
|
||||||
|
|
||||||
/* credit: https://stackoverflow.com/questions/29049686/is-there-a-better-way-to-pass-formatted-output-to-outputdebugstring */
|
/* 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;
|
INT cbFormatString = 0;
|
||||||
va_list args;
|
va_list args;
|
||||||
PCHAR szDebugString = NULL;
|
PCHAR szDebugString = NULL;
|
||||||
size_t st_Offset = 0;
|
size_t stOffset = 0;
|
||||||
|
|
||||||
va_start(args, kszDebugFormatString);
|
va_start(args, kszDebugFormatString);
|
||||||
|
|
||||||
cbFormatString = _scprintf("[%s:%d] ", kwszFunction, iLineNumber) * sizeof(CHAR);
|
cbFormatString = _scprintf("[%s:%d] ", kwszFunction, iLineNumber);
|
||||||
cbFormatString += _vscprintf(kszDebugFormatString, args) * sizeof(CHAR) + 2;
|
cbFormatString += _vscprintf(kszDebugFormatString, args);
|
||||||
|
cbFormatString += 2;
|
||||||
|
|
||||||
/* Depending on the size of the format string, allocate space on the stack or the heap. */
|
/* Depending on the size of the format string, allocate space on the stack or the heap. */
|
||||||
szDebugString = (PCHAR)_malloca(cbFormatString);
|
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. */
|
/* Populate the buffer with the contents of the format string. */
|
||||||
StringCbPrintfA(szDebugString, cbFormatString, "[%s:%d] ", kwszFunction, iLineNumber);
|
StringCbPrintfA(szDebugString, cbFormatString, "[%s:%d] ", kwszFunction, iLineNumber);
|
||||||
StringCbLengthA(szDebugString, cbFormatString, &st_Offset);
|
StringCbLengthA(szDebugString, cbFormatString, &stOffset);
|
||||||
StringCbVPrintfA(&szDebugString[st_Offset / sizeof(CHAR)], cbFormatString - st_Offset, kszDebugFormatString, args);
|
StringCbVPrintfA(&szDebugString[stOffset], cbFormatString - stOffset, kszDebugFormatString, args);
|
||||||
|
|
||||||
OutputDebugStringA(szDebugString);
|
OutputDebugStringA(szDebugString);
|
||||||
|
|
||||||
_freea(szDebugString);
|
_freea(szDebugString);
|
||||||
va_end(args);
|
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, ...);
|
VOID _DBGPRINT(PCSTR kszFunction, INT iLineNumber, LPCSTR kszDebugFormatString, ...);
|
||||||
#define DBGPRINT(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)
|
NTSTATUS LGIddMonitorAssignSwapChain(IDDCX_MONITOR monitor, const IDARG_IN_SETSWAPCHAIN* inArgs)
|
||||||
{
|
{
|
||||||
auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
|
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,16 +46,19 @@ NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING Reg
|
|||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
|
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
|
||||||
|
return status;
|
||||||
|
|
||||||
|
fail:
|
||||||
#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0
|
#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0
|
||||||
WPP_CLEANUP();
|
WPP_CLEANUP();
|
||||||
#else
|
#else
|
||||||
WPP_CLEANUP(DriverObject);
|
WPP_CLEANUP(DriverObject);
|
||||||
#endif
|
#endif
|
||||||
return status;
|
return status;
|
||||||
}
|
|
||||||
|
|
||||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS LGIddEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
|
NTSTATUS LGIddEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
|
||||||
|
@ -38,24 +38,36 @@
|
|||||||
<None Include="cpp.hint" />
|
<None Include="cpp.hint" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="CD3D12CommandQueue.cpp" />
|
||||||
|
<ClCompile Include="CFrameBufferPool.cpp" />
|
||||||
|
<ClCompile Include="CFrameBufferResource.cpp" />
|
||||||
<ClCompile Include="CIndirectDeviceContext.cpp" />
|
<ClCompile Include="CIndirectDeviceContext.cpp" />
|
||||||
<ClCompile Include="CIndirectMonitorContext.cpp" />
|
<ClCompile Include="CIndirectMonitorContext.cpp" />
|
||||||
|
<ClCompile Include="CInteropResourcePool.cpp" />
|
||||||
|
<ClCompile Include="CInteropResource.cpp" />
|
||||||
<ClCompile Include="CIVSHMEM.cpp" />
|
<ClCompile Include="CIVSHMEM.cpp" />
|
||||||
<ClCompile Include="CPlatformInfo.cpp" />
|
<ClCompile Include="CPlatformInfo.cpp" />
|
||||||
<ClCompile Include="CSwapChainProcessor.cpp" />
|
<ClCompile Include="CSwapChainProcessor.cpp" />
|
||||||
|
<ClCompile Include="CD3D12Device.cpp" />
|
||||||
<ClCompile Include="Debug.cpp" />
|
<ClCompile Include="Debug.cpp" />
|
||||||
<ClCompile Include="Device.cpp" />
|
<ClCompile Include="Device.cpp" />
|
||||||
<ClCompile Include="Direct3DDevice.cpp" />
|
<ClCompile Include="CD3D11Device.cpp" />
|
||||||
<ClCompile Include="Driver.cpp" />
|
<ClCompile Include="Driver.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="CD3D12CommandQueue.h" />
|
||||||
|
<ClInclude Include="CFrameBufferPool.h" />
|
||||||
|
<ClInclude Include="CFrameBufferResource.h" />
|
||||||
<ClInclude Include="CIndirectMonitorContext.h" />
|
<ClInclude Include="CIndirectMonitorContext.h" />
|
||||||
|
<ClInclude Include="CInteropResourcePool.h" />
|
||||||
|
<ClInclude Include="CInteropResource.h" />
|
||||||
<ClInclude Include="CIVSHMEM.h" />
|
<ClInclude Include="CIVSHMEM.h" />
|
||||||
<ClInclude Include="CPlatformInfo.h" />
|
<ClInclude Include="CPlatformInfo.h" />
|
||||||
<ClInclude Include="CSwapChainProcessor.h" />
|
<ClInclude Include="CSwapChainProcessor.h" />
|
||||||
|
<ClInclude Include="CD3D12Device.h" />
|
||||||
<ClInclude Include="Debug.h" />
|
<ClInclude Include="Debug.h" />
|
||||||
<ClInclude Include="Device.h" />
|
<ClInclude Include="Device.h" />
|
||||||
<ClInclude Include="Direct3DDevice.h" />
|
<ClInclude Include="CD3D11Device.h" />
|
||||||
<ClInclude Include="Driver.h" />
|
<ClInclude Include="Driver.h" />
|
||||||
<ClInclude Include="CIndirectDeviceContext.h" />
|
<ClInclude Include="CIndirectDeviceContext.h" />
|
||||||
<ClInclude Include="Public.h" />
|
<ClInclude Include="Public.h" />
|
||||||
@ -257,7 +269,7 @@
|
|||||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;$(ProjectDir)..\..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;$(ProjectDir)..\..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib;d3d12.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<DriverSign>
|
<DriverSign>
|
||||||
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
||||||
@ -272,7 +284,7 @@
|
|||||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;$(ProjectDir)..\..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;$(ProjectDir)..\..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib;d3d12.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<DriverSign>
|
<DriverSign>
|
||||||
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
||||||
|
@ -48,9 +48,6 @@
|
|||||||
<ClInclude Include="CSwapChainProcessor.h">
|
<ClInclude Include="CSwapChainProcessor.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Direct3DDevice.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="CIVSHMEM.h">
|
<ClInclude Include="CIVSHMEM.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -60,6 +57,27 @@
|
|||||||
<ClInclude Include="CPlatformInfo.h">
|
<ClInclude Include="CPlatformInfo.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Device.cpp">
|
<ClCompile Include="Device.cpp">
|
||||||
@ -77,9 +95,6 @@
|
|||||||
<ClCompile Include="CSwapChainProcessor.cpp">
|
<ClCompile Include="CSwapChainProcessor.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Direct3DDevice.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="CIVSHMEM.cpp">
|
<ClCompile Include="CIVSHMEM.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -89,5 +104,26 @@
|
|||||||
<ClCompile Include="CPlatformInfo.cpp">
|
<ClCompile Include="CPlatformInfo.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</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>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -1 +1 @@
|
|||||||
Subproject commit eddecb588839b2b88ac3a77e0a064daa96aab541
|
Subproject commit f8482c14aae84edf5fc0f3a8c5d3ade0c29df219
|
Loading…
x
Reference in New Issue
Block a user