mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-20 22:32:01 +00:00
[idd] disable HDR and post-processing when in software mode
This commit is contained in:
@@ -60,10 +60,13 @@ static void CALLBACK _D3D12DebugCallback(
|
|||||||
description);
|
description);
|
||||||
}
|
}
|
||||||
|
|
||||||
CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem, UINT64 &alignSize)
|
CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem,
|
||||||
|
UINT64 &alignSize, bool enableCompute)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
m_computeEnabled = enableCompute;
|
||||||
|
|
||||||
hr = CreateDXGIFactory2(m_debug ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&m_factory));
|
hr = CreateDXGIFactory2(m_debug ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&m_factory));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
@@ -132,8 +135,9 @@ CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem, UINT64 &alignSize
|
|||||||
m_indirectCopy ? CD3D12CommandQueue::NORMAL : CD3D12CommandQueue::FAST))
|
m_indirectCopy ? CD3D12CommandQueue::NORMAL : CD3D12CommandQueue::FAST))
|
||||||
return InitResult::FAILURE;
|
return InitResult::FAILURE;
|
||||||
|
|
||||||
if (!m_computeQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COMPUTE, L"Compute",
|
if (m_computeEnabled &&
|
||||||
CD3D12CommandQueue::FAST))
|
!m_computeQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||||
|
L"Compute", CD3D12CommandQueue::FAST))
|
||||||
return InitResult::FAILURE;
|
return InitResult::FAILURE;
|
||||||
|
|
||||||
DEBUG_INFO("Created CD3D12Device");
|
DEBUG_INFO("Created CD3D12Device");
|
||||||
@@ -160,7 +164,8 @@ void CD3D12Device::WaitForIdle()
|
|||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_copyQueue); ++i)
|
for (int i = 0; i < ARRAYSIZE(m_copyQueue); ++i)
|
||||||
drain(m_copyQueue[i]);
|
drain(m_copyQueue[i]);
|
||||||
drain(m_computeQueue);
|
if (m_computeEnabled)
|
||||||
|
drain(m_computeQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CD3D12Device::HeapTest()
|
bool CD3D12Device::HeapTest()
|
||||||
@@ -233,6 +238,12 @@ CD3D12CommandQueue * CD3D12Device::GetCopyQueue()
|
|||||||
|
|
||||||
CD3D12CommandQueue * CD3D12Device::GetComputeQueue()
|
CD3D12CommandQueue * CD3D12Device::GetComputeQueue()
|
||||||
{
|
{
|
||||||
|
if (!m_computeEnabled)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Compute queue requested while compute processing is disabled");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
for (int c = 0; c < 100; ++c)
|
for (int c = 0; c < 100; ++c)
|
||||||
{
|
{
|
||||||
if (m_computeQueue.IsReady())
|
if (m_computeQueue.IsReady())
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ struct CD3D12Device
|
|||||||
CD3D12CommandQueue m_copyQueue[4];
|
CD3D12CommandQueue m_copyQueue[4];
|
||||||
unsigned m_copyQueueIndex = 0;
|
unsigned m_copyQueueIndex = 0;
|
||||||
CD3D12CommandQueue m_computeQueue;
|
CD3D12CommandQueue m_computeQueue;
|
||||||
|
bool m_computeEnabled = false;
|
||||||
|
|
||||||
bool HeapTest();
|
bool HeapTest();
|
||||||
|
|
||||||
@@ -66,7 +67,8 @@ struct CD3D12Device
|
|||||||
SUCCESS
|
SUCCESS
|
||||||
};
|
};
|
||||||
|
|
||||||
InitResult Init(CIVSHMEM &ivshmem, UINT64 &alignSize);
|
InitResult Init(CIVSHMEM &ivshmem, UINT64 &alignSize,
|
||||||
|
bool enableCompute);
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
// Wait for all command queues to finish in-flight GPU work and run their
|
// Wait for all command queues to finish in-flight GPU work and run their
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ static const BYTE EDID_MANUFACTURE_YEAR_2026 = 36; // 1990 + 36 = 2026
|
|||||||
static const BYTE EDID_VERSION = 1;
|
static const BYTE EDID_VERSION = 1;
|
||||||
static const BYTE EDID_REVISION = 4;
|
static const BYTE EDID_REVISION = 4;
|
||||||
|
|
||||||
|
static const BYTE EDID_VIDEO_INPUT_DIGITAL_8BPC_HDMI_A = 0xa2;
|
||||||
static const BYTE EDID_VIDEO_INPUT_DIGITAL_10BPC_HDMI_A = 0xb2;
|
static const BYTE EDID_VIDEO_INPUT_DIGITAL_10BPC_HDMI_A = 0xb2;
|
||||||
static const BYTE EDID_HORIZONTAL_SIZE_CM = 52;
|
static const BYTE EDID_HORIZONTAL_SIZE_CM = 52;
|
||||||
static const BYTE EDID_VERTICAL_SIZE_CM = 29;
|
static const BYTE EDID_VERTICAL_SIZE_CM = 29;
|
||||||
@@ -316,17 +317,16 @@ static WORD EdidChromaticity(double value)
|
|||||||
return (WORD)min(1023.0, max(0.0, value * 1024.0 + 0.5));
|
return (WORD)min(1023.0, max(0.0, value * 1024.0 + 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetChromaticityCoordinates(BYTE coordinates[10])
|
static void SetChromaticityCoordinates(BYTE coordinates[10], bool hdr)
|
||||||
{
|
{
|
||||||
// The virtual display transports HDR in the BT.2020 container. Describe
|
// Describe the wire gamut. Accelerated HDR uses the BT.2020 container;
|
||||||
// that full container gamut and its D65 white point rather than leaving an
|
// software rendering is SDR-only and uses the standard sRGB/BT.709 gamut.
|
||||||
// invalid all-zero base-block colour volume.
|
const WORD rx = EdidChromaticity(hdr ? 0.7080 : 0.6400);
|
||||||
const WORD rx = EdidChromaticity(0.7080);
|
const WORD ry = EdidChromaticity(hdr ? 0.2920 : 0.3300);
|
||||||
const WORD ry = EdidChromaticity(0.2920);
|
const WORD gx = EdidChromaticity(hdr ? 0.1700 : 0.3000);
|
||||||
const WORD gx = EdidChromaticity(0.1700);
|
const WORD gy = EdidChromaticity(hdr ? 0.7970 : 0.6000);
|
||||||
const WORD gy = EdidChromaticity(0.7970);
|
const WORD bx = EdidChromaticity(hdr ? 0.1310 : 0.1500);
|
||||||
const WORD bx = EdidChromaticity(0.1310);
|
const WORD by = EdidChromaticity(hdr ? 0.0460 : 0.0600);
|
||||||
const WORD by = EdidChromaticity(0.0460);
|
|
||||||
const WORD wx = EdidChromaticity(0.3127);
|
const WORD wx = EdidChromaticity(0.3127);
|
||||||
const WORD wy = EdidChromaticity(0.3290);
|
const WORD wy = EdidChromaticity(0.3290);
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ static void SetChromaticityCoordinates(BYTE coordinates[10])
|
|||||||
coordinates[9] = (BYTE)(wy >> 2);
|
coordinates[9] = (BYTE)(wy >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitEdidBaseBlock(EdidBaseBlock& base)
|
static void InitEdidBaseBlock(EdidBaseBlock& base, bool hdr)
|
||||||
{
|
{
|
||||||
memcpy(base.header, EDID_HEADER, sizeof(base.header));
|
memcpy(base.header, EDID_HEADER, sizeof(base.header));
|
||||||
|
|
||||||
@@ -358,12 +358,14 @@ static void InitEdidBaseBlock(EdidBaseBlock& base)
|
|||||||
base.version = EDID_VERSION;
|
base.version = EDID_VERSION;
|
||||||
base.revision = EDID_REVISION;
|
base.revision = EDID_REVISION;
|
||||||
|
|
||||||
base.videoInputDefinition = EDID_VIDEO_INPUT_DIGITAL_10BPC_HDMI_A;
|
base.videoInputDefinition = hdr ?
|
||||||
|
EDID_VIDEO_INPUT_DIGITAL_10BPC_HDMI_A :
|
||||||
|
EDID_VIDEO_INPUT_DIGITAL_8BPC_HDMI_A;
|
||||||
base.horizontalSizeCm = EDID_HORIZONTAL_SIZE_CM;
|
base.horizontalSizeCm = EDID_HORIZONTAL_SIZE_CM;
|
||||||
base.verticalSizeCm = EDID_VERTICAL_SIZE_CM;
|
base.verticalSizeCm = EDID_VERTICAL_SIZE_CM;
|
||||||
base.displayGamma = EDID_DISPLAY_GAMMA_2_2;
|
base.displayGamma = EDID_DISPLAY_GAMMA_2_2;
|
||||||
base.supportedFeatures = EDID_FEATURES_PREFERRED_TIMING_RGB;
|
base.supportedFeatures = EDID_FEATURES_PREFERRED_TIMING_RGB;
|
||||||
SetChromaticityCoordinates(base.chromaticityCoordinates);
|
SetChromaticityCoordinates(base.chromaticityCoordinates, hdr);
|
||||||
|
|
||||||
for (UINT i = 0; i < EDID_STANDARD_TIMING_COUNT; ++i)
|
for (UINT i = 0; i < EDID_STANDARD_TIMING_COUNT; ++i)
|
||||||
base.standardTimings[i] = MakeUnusedStandardTiming();
|
base.standardTimings[i] = MakeUnusedStandardTiming();
|
||||||
@@ -572,12 +574,12 @@ bool CEdid::WriteDetailedTiming(BYTE* dtd, const CSettings::DisplayMode& mode)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEdid::Build(const CSettings::DisplayModes& modes)
|
void CEdid::Build(const CSettings::DisplayModes& modes, bool hdr)
|
||||||
{
|
{
|
||||||
m_data.assign(static_cast<std::vector<BYTE, std::allocator<BYTE>>::size_type>(EDID_BLOCK_SIZE) * 2, 0);
|
m_data.assign(static_cast<std::vector<BYTE, std::allocator<BYTE>>::size_type>(EDID_BLOCK_SIZE) * 2, 0);
|
||||||
|
|
||||||
EdidBaseBlock baseBlock = {};
|
EdidBaseBlock baseBlock = {};
|
||||||
InitEdidBaseBlock(baseBlock);
|
InitEdidBaseBlock(baseBlock, hdr);
|
||||||
|
|
||||||
CSettings::DisplayModes sorted = modes;
|
CSettings::DisplayModes sorted = modes;
|
||||||
std::stable_sort(sorted.begin(), sorted.end(),
|
std::stable_sort(sorted.begin(), sorted.end(),
|
||||||
@@ -625,10 +627,13 @@ void CEdid::Build(const CSettings::DisplayModes& modes)
|
|||||||
ctaBlock.revision = CTA_REVISION;
|
ctaBlock.revision = CTA_REVISION;
|
||||||
|
|
||||||
UINT dataOffset = CTA_HEADER_SIZE;
|
UINT dataOffset = CTA_HEADER_SIZE;
|
||||||
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdrStaticMetadataDataBlock ());
|
if (hdr)
|
||||||
AppendCtaDataBlock(cta, dataOffset, MakeCtaColorimetryDataBlock ());
|
{
|
||||||
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiForumVendorSpecificDataBlock());
|
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdrStaticMetadataDataBlock ());
|
||||||
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiVendorSpecificDataBlock ());
|
AppendCtaDataBlock(cta, dataOffset, MakeCtaColorimetryDataBlock ());
|
||||||
|
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiForumVendorSpecificDataBlock());
|
||||||
|
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiVendorSpecificDataBlock ());
|
||||||
|
}
|
||||||
|
|
||||||
ctaBlock.dtdOffset = (BYTE)dataOffset;
|
ctaBlock.dtdOffset = (BYTE)dataOffset;
|
||||||
ctaBlock.flags = 0x00;
|
ctaBlock.flags = 0x00;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
class CEdid
|
class CEdid
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Build(const CSettings::DisplayModes& modes);
|
void Build(const CSettings::DisplayModes& modes, bool hdr);
|
||||||
|
|
||||||
const BYTE* Data() const { return m_data.empty() ? nullptr : m_data.data(); }
|
const BYTE* Data() const { return m_data.empty() ? nullptr : m_data.data(); }
|
||||||
UINT Size() const { return (UINT)m_data.size(); }
|
UINT Size() const { return (UINT)m_data.size(); }
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
#include "VersionInfo.h"
|
#include "VersionInfo.h"
|
||||||
|
|
||||||
|
#include <dxgi1_2.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
static const struct LGMPQueueConfig FRAME_QUEUE_CONFIG =
|
static const struct LGMPQueueConfig FRAME_QUEUE_CONFIG =
|
||||||
@@ -67,6 +68,7 @@ void CIndirectDeviceContext::QueryIddCxCapabilities()
|
|||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
m_iddCxVersion = 0;
|
m_iddCxVersion = 0;
|
||||||
|
m_hasIddCx110DDIs = false;
|
||||||
m_canProcessFP16 = false;
|
m_canProcessFP16 = false;
|
||||||
DEBUG_ERROR_HR(status, "IddCxGetVersion Failed");
|
DEBUG_ERROR_HR(status, "IddCxGetVersion Failed");
|
||||||
return;
|
return;
|
||||||
@@ -89,10 +91,15 @@ void CIndirectDeviceContext::QueryIddCxCapabilities()
|
|||||||
const bool hasIddCx110DDIs = false;
|
const bool hasIddCx110DDIs = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_canProcessFP16 = m_iddCxVersion >= IDDCX_VERSION_1_10 && hasIddCx110DDIs;
|
m_hasIddCx110DDIs =
|
||||||
|
m_iddCxVersion >= IDDCX_VERSION_1_10 && hasIddCx110DDIs;
|
||||||
|
m_canProcessFP16 = !m_softwareMode && m_hasIddCx110DDIs;
|
||||||
|
|
||||||
DEBUG_INFO("IddCx version: 0x%04x", m_iddCxVersion);
|
DEBUG_INFO("IddCx version: 0x%04x", m_iddCxVersion);
|
||||||
DEBUG_INFO("IddCx 1.10 HDR/WCG DDIs: %s", m_canProcessFP16 ? "available" : "unavailable");
|
DEBUG_INFO("IddCx 1.10 HDR/WCG DDIs: %s",
|
||||||
|
m_hasIddCx110DDIs ? "available" : "unavailable");
|
||||||
|
if (m_softwareMode && m_hasIddCx110DDIs)
|
||||||
|
DEBUG_INFO("HDR/WCG disabled for software rendering");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIndirectDeviceContext::PopulateDefaultModes()
|
void CIndirectDeviceContext::PopulateDefaultModes()
|
||||||
@@ -117,7 +124,7 @@ void CIndirectDeviceContext::InitializeEdid()
|
|||||||
{
|
{
|
||||||
AcquireSRWLockExclusive(&m_modeLock);
|
AcquireSRWLockExclusive(&m_modeLock);
|
||||||
if (!m_edid.Size())
|
if (!m_edid.Size())
|
||||||
m_edid.Build(m_displayModes);
|
m_edid.Build(m_displayModes, CanProcessFP16());
|
||||||
ReleaseSRWLockExclusive(&m_modeLock);
|
ReleaseSRWLockExclusive(&m_modeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,6 +201,68 @@ void CIndirectDeviceContext::InitAdapter()
|
|||||||
m_ivshmemOpened = true;
|
m_ivshmemOpened = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select the render adapter before advertising capabilities. If no hardware
|
||||||
|
// adapter is available, this is a software-rendered display and must remain
|
||||||
|
// SDR-only; the software path must never depend on compute processing.
|
||||||
|
bool havePreferredRenderAdapter = false;
|
||||||
|
LUID preferredRenderAdapter = {};
|
||||||
|
IDXGIFactory1 * factory = NULL;
|
||||||
|
HRESULT factoryStatus = CreateDXGIFactory(
|
||||||
|
__uuidof(IDXGIFactory1), (void **)&factory);
|
||||||
|
if (FAILED(factoryStatus))
|
||||||
|
DEBUG_ERROR_HR(factoryStatus, "CreateDXGIFactory Failed");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (UINT i = 0;; ++i)
|
||||||
|
{
|
||||||
|
IDXGIAdapter1 * dxgiAdapter = nullptr;
|
||||||
|
HRESULT enumStatus = factory->EnumAdapters1(i, &dxgiAdapter);
|
||||||
|
if (enumStatus == DXGI_ERROR_NOT_FOUND)
|
||||||
|
break;
|
||||||
|
if (FAILED(enumStatus))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR_HR(enumStatus, "Failed to enumerate DXGI adapter %u", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_ADAPTER_DESC1 adapterDesc = {};
|
||||||
|
HRESULT descStatus = dxgiAdapter->GetDesc1(&adapterDesc);
|
||||||
|
dxgiAdapter->Release();
|
||||||
|
if (FAILED(descStatus))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR_HR(descStatus, "Failed to query DXGI adapter %u", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ||
|
||||||
|
(adapterDesc.VendorId == 0x1414 && adapterDesc.DeviceId == 0x008c))
|
||||||
|
{
|
||||||
|
DEBUG_INFO("Ignoring software render adapter %ls", adapterDesc.Description);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((adapterDesc.VendorId == 0x1b36 && adapterDesc.DeviceId == 0x000d) || // QXL
|
||||||
|
(adapterDesc.VendorId == 0x1234 && adapterDesc.DeviceId == 0x1111)) // QEMU Standard VGA
|
||||||
|
{
|
||||||
|
DEBUG_INFO("Ignoring display-only adapter %ls (vendor 0x%04x, device 0x%04x)",
|
||||||
|
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_INFO("Selected render adapter %ls (vendor 0x%04x, device 0x%04x)",
|
||||||
|
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
|
||||||
|
preferredRenderAdapter = adapterDesc.AdapterLuid;
|
||||||
|
havePreferredRenderAdapter = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_softwareMode = !havePreferredRenderAdapter;
|
||||||
|
if (m_softwareMode)
|
||||||
|
DEBUG_INFO("No hardware render adapter available; using SDR software mode");
|
||||||
|
|
||||||
QueryIddCxCapabilities();
|
QueryIddCxCapabilities();
|
||||||
DEBUG_TRACE("Loading configured display modes");
|
DEBUG_TRACE("Loading configured display modes");
|
||||||
PopulateDefaultModes();
|
PopulateDefaultModes();
|
||||||
@@ -218,7 +287,7 @@ void CIndirectDeviceContext::InitAdapter()
|
|||||||
*/
|
*/
|
||||||
caps.Flags = IDDCX_ADAPTER_FLAGS_USE_SMALLEST_MODE;
|
caps.Flags = IDDCX_ADAPTER_FLAGS_USE_SMALLEST_MODE;
|
||||||
#ifdef HAS_IDDCX_110
|
#ifdef HAS_IDDCX_110
|
||||||
if (CanUseIddCx110DDIs())
|
if (CanProcessFP16())
|
||||||
caps.Flags |= IDDCX_ADAPTER_FLAGS_CAN_PROCESS_FP16;
|
caps.Flags |= IDDCX_ADAPTER_FLAGS_CAN_PROCESS_FP16;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -250,12 +319,17 @@ void CIndirectDeviceContext::InitAdapter()
|
|||||||
DEBUG_INFO("Calling IddCxAdapterInitAsync with flags 0x%08x",
|
DEBUG_INFO("Calling IddCxAdapterInitAsync with flags 0x%08x",
|
||||||
caps.Flags);
|
caps.Flags);
|
||||||
NTSTATUS status = IddCxAdapterInitAsync(&init, &initOut);
|
NTSTATUS status = IddCxAdapterInitAsync(&init, &initOut);
|
||||||
if (!NT_SUCCESS(status) && CanUseIddCx110DDIs())
|
if (!NT_SUCCESS(status) && CanProcessFP16())
|
||||||
{
|
{
|
||||||
DEBUG_WARN(
|
DEBUG_WARN(
|
||||||
"IddCxAdapterInitAsync rejected FP16 adapter capabilities (0x%08x), retrying without HDR/WCG",
|
"IddCxAdapterInitAsync rejected FP16 adapter capabilities (0x%08x), retrying without HDR/WCG",
|
||||||
status);
|
status);
|
||||||
m_canProcessFP16 = false;
|
m_canProcessFP16 = false;
|
||||||
|
// The monitor has not been created yet, so replace the provisional HDR
|
||||||
|
// EDID before Windows can observe it.
|
||||||
|
AcquireSRWLockExclusive(&m_modeLock);
|
||||||
|
m_edid.Build(m_displayModes, false);
|
||||||
|
ReleaseSRWLockExclusive(&m_modeLock);
|
||||||
caps.Flags = (IDDCX_ADAPTER_FLAGS)(caps.Flags & ~IDDCX_ADAPTER_FLAGS_CAN_PROCESS_FP16);
|
caps.Flags = (IDDCX_ADAPTER_FLAGS)(caps.Flags & ~IDDCX_ADAPTER_FLAGS_CAN_PROCESS_FP16);
|
||||||
ZeroMemory(&initOut, sizeof(initOut));
|
ZeroMemory(&initOut, sizeof(initOut));
|
||||||
status = IddCxAdapterInitAsync(&init, &initOut);
|
status = IddCxAdapterInitAsync(&init, &initOut);
|
||||||
@@ -281,63 +355,12 @@ void CIndirectDeviceContext::InitAdapter()
|
|||||||
|
|
||||||
// Try to co-exist with the virtual video device by telling IddCx which
|
// Try to co-exist with the virtual video device by telling IddCx which
|
||||||
// hardware adapter we prefer to render on.
|
// hardware adapter we prefer to render on.
|
||||||
IDXGIFactory * factory = NULL;
|
if (havePreferredRenderAdapter)
|
||||||
HRESULT factoryStatus = CreateDXGIFactory(
|
|
||||||
__uuidof(IDXGIFactory), (void **)&factory);
|
|
||||||
if (FAILED(factoryStatus))
|
|
||||||
DEBUG_ERROR_HR(factoryStatus, "CreateDXGIFactory Failed");
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
bool renderAdapterSelected = false;
|
IDARG_IN_ADAPTERSETRENDERADAPTER args = {};
|
||||||
for (UINT i = 0;; ++i)
|
args.PreferredRenderAdapter = preferredRenderAdapter;
|
||||||
{
|
IddCxAdapterSetRenderAdapter(m_adapter, &args);
|
||||||
IDXGIAdapter * dxgiAdapter = nullptr;
|
DEBUG_INFO("Preferred render adapter set");
|
||||||
HRESULT enumStatus = factory->EnumAdapters(i, &dxgiAdapter);
|
|
||||||
if (enumStatus == DXGI_ERROR_NOT_FOUND)
|
|
||||||
break;
|
|
||||||
if (FAILED(enumStatus))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR_HR(enumStatus, "Failed to enumerate DXGI adapter %u", i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DXGI_ADAPTER_DESC adapterDesc = {};
|
|
||||||
HRESULT descStatus = dxgiAdapter->GetDesc(&adapterDesc);
|
|
||||||
dxgiAdapter->Release();
|
|
||||||
if (FAILED(descStatus))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR_HR(descStatus, "Failed to query DXGI adapter %u", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapterDesc.VendorId == 0x1414 && adapterDesc.DeviceId == 0x008c)
|
|
||||||
{
|
|
||||||
DEBUG_INFO("Ignoring software render adapter %ls", adapterDesc.Description);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((adapterDesc.VendorId == 0x1b36 && adapterDesc.DeviceId == 0x000d) || // QXL
|
|
||||||
(adapterDesc.VendorId == 0x1234 && adapterDesc.DeviceId == 0x1111)) // QEMU Standard VGA
|
|
||||||
{
|
|
||||||
DEBUG_INFO("Ignoring display-only adapter %ls (vendor 0x%04x, device 0x%04x)",
|
|
||||||
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_INFO("Selecting render adapter %ls (vendor 0x%04x, device 0x%04x)",
|
|
||||||
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
|
|
||||||
IDARG_IN_ADAPTERSETRENDERADAPTER args = {};
|
|
||||||
args.PreferredRenderAdapter = adapterDesc.AdapterLuid;
|
|
||||||
IddCxAdapterSetRenderAdapter(m_adapter, &args);
|
|
||||||
DEBUG_INFO("Preferred render adapter set");
|
|
||||||
renderAdapterSelected = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!renderAdapterSelected)
|
|
||||||
DEBUG_INFO("No preferred hardware render adapter was selected");
|
|
||||||
|
|
||||||
factory->Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto * wrapper = WdfObjectGet_CIndirectDeviceContextWrapper(m_adapter);
|
auto * wrapper = WdfObjectGet_CIndirectDeviceContextWrapper(m_adapter);
|
||||||
@@ -684,7 +707,7 @@ NTSTATUS CIndirectDeviceContext::ParseMonitorDescription2(
|
|||||||
mode->Size = sizeof(IDDCX_MONITOR_MODE2);
|
mode->Size = sizeof(IDDCX_MONITOR_MODE2);
|
||||||
mode->Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR;
|
mode->Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR;
|
||||||
FillSignalInfo(mode->MonitorVideoSignalInfo, it->width, it->height, it->refresh, true);
|
FillSignalInfo(mode->MonitorVideoSignalInfo, it->width, it->height, it->refresh, true);
|
||||||
mode->BitsPerComponent = GetWireBitsPerComponent(CanUseIddCx110DDIs());
|
mode->BitsPerComponent = GetWireBitsPerComponent(CanProcessFP16());
|
||||||
|
|
||||||
if (it->preferred)
|
if (it->preferred)
|
||||||
outArgs->PreferredMonitorModeIdx =
|
outArgs->PreferredMonitorModeIdx =
|
||||||
@@ -716,7 +739,7 @@ NTSTATUS CIndirectDeviceContext::MonitorQueryTargetModes2(
|
|||||||
ZeroMemory(mode, sizeof(*mode));
|
ZeroMemory(mode, sizeof(*mode));
|
||||||
mode->Size = sizeof(IDDCX_TARGET_MODE2);
|
mode->Size = sizeof(IDDCX_TARGET_MODE2);
|
||||||
FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, it->width, it->height, it->refresh, false);
|
FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, it->width, it->height, it->refresh, false);
|
||||||
mode->BitsPerComponent = GetWireBitsPerComponent(CanUseIddCx110DDIs());
|
mode->BitsPerComponent = GetWireBitsPerComponent(CanProcessFP16());
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|||||||
@@ -115,7 +115,9 @@ private:
|
|||||||
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
||||||
FrameType m_frameType = FRAME_TYPE_INVALID;
|
FrameType m_frameType = FRAME_TYPE_INVALID;
|
||||||
UINT m_iddCxVersion = 0;
|
UINT m_iddCxVersion = 0;
|
||||||
|
bool m_hasIddCx110DDIs = false;
|
||||||
bool m_canProcessFP16 = false;
|
bool m_canProcessFP16 = false;
|
||||||
|
bool m_softwareMode = true;
|
||||||
|
|
||||||
// HDR state from EvtIddCxMonitorSetDefaultHdrMetadata (IddCx 1.10+)
|
// HDR state from EvtIddCxMonitorSetDefaultHdrMetadata (IddCx 1.10+)
|
||||||
// Protected by m_hdrLock - accessed from both the IDD callback thread
|
// Protected by m_hdrLock - accessed from both the IDD callback thread
|
||||||
@@ -147,7 +149,6 @@ private:
|
|||||||
std::shared_ptr<const D12ColorTransform> m_colorTransform;
|
std::shared_ptr<const D12ColorTransform> m_colorTransform;
|
||||||
|
|
||||||
void QueryIddCxCapabilities();
|
void QueryIddCxCapabilities();
|
||||||
bool CanUseIddCx110DDIs() const { return m_canProcessFP16; }
|
|
||||||
|
|
||||||
void ScheduleInitRetry();
|
void ScheduleInitRetry();
|
||||||
void StopInitRetry();
|
void StopInitRetry();
|
||||||
@@ -211,7 +212,9 @@ public:
|
|||||||
|
|
||||||
size_t GetAlignSize () const { return m_alignSize ; }
|
size_t GetAlignSize () const { return m_alignSize ; }
|
||||||
size_t GetMaxFrameSize() const { return m_maxFrameSize ; }
|
size_t GetMaxFrameSize() const { return m_maxFrameSize ; }
|
||||||
|
bool HasIddCx110DDIs() const { return m_hasIddCx110DDIs; }
|
||||||
bool CanProcessFP16 () const { return m_canProcessFP16; }
|
bool CanProcessFP16 () const { return m_canProcessFP16; }
|
||||||
|
bool IsSoftwareMode () const { return m_softwareMode ; }
|
||||||
|
|
||||||
struct PreparedFrameBuffer
|
struct PreparedFrameBuffer
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID re
|
|||||||
|
|
||||||
UINT64 alignSize = CPlatformInfo::GetPageSize();
|
UINT64 alignSize = CPlatformInfo::GetPageSize();
|
||||||
dx12Device = std::make_shared<CD3D12Device>(renderAdapter);
|
dx12Device = std::make_shared<CD3D12Device>(renderAdapter);
|
||||||
CD3D12Device::InitResult r = dx12Device->Init(m_devContext->GetIVSHMEM(), alignSize);
|
CD3D12Device::InitResult r = dx12Device->Init(
|
||||||
|
m_devContext->GetIVSHMEM(), alignSize, !dx11Device->IsSoftware());
|
||||||
if (r == CD3D12Device::RETRY)
|
if (r == CD3D12Device::RETRY)
|
||||||
{
|
{
|
||||||
dx12Device.reset();
|
dx12Device.reset();
|
||||||
|
|||||||
@@ -30,6 +30,46 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool NearlyEqual(float a, float b, float tolerance)
|
||||||
|
{
|
||||||
|
const float delta = a - b;
|
||||||
|
return delta >= -tolerance && delta <= tolerance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsIdentityColorTransform(const D12ColorTransform& transform)
|
||||||
|
{
|
||||||
|
static const float matrixTolerance = 1.0f / 1048576.0f;
|
||||||
|
static const float lutTolerance = 1.0f / 65535.0f;
|
||||||
|
|
||||||
|
if (transform.matrixEnabled)
|
||||||
|
{
|
||||||
|
for (unsigned row = 0; row < 3; ++row)
|
||||||
|
for (unsigned column = 0; column < 4; ++column)
|
||||||
|
{
|
||||||
|
const float expected = row == column ? 1.0f : 0.0f;
|
||||||
|
const float effective =
|
||||||
|
transform.matrix[row][column] * transform.scalar;
|
||||||
|
if (!NearlyEqual(effective, expected, matrixTolerance))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.lutEnabled)
|
||||||
|
for (unsigned i = 0; i < 4096; ++i)
|
||||||
|
{
|
||||||
|
const float expected = (float)i / 4095.0f;
|
||||||
|
if (!NearlyEqual(transform.lut[i][0], expected, lutTolerance) ||
|
||||||
|
!NearlyEqual(transform.lut[i][1], expected, lutTolerance) ||
|
||||||
|
!NearlyEqual(transform.lut[i][2], expected, lutTolerance))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void CopyHDRMetadata(D12FrameFormat& dst, const D12FrameFormat& src)
|
static void CopyHDRMetadata(D12FrameFormat& dst, const D12FrameFormat& src)
|
||||||
{
|
{
|
||||||
dst.hdrMetadata = src.hdrMetadata;
|
dst.hdrMetadata = src.hdrMetadata;
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ struct D12ColorTransform
|
|||||||
float lut[4096][4] = {};
|
float lut[4096][4] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool IsIdentityColorTransform(const D12ColorTransform& transform);
|
||||||
|
|
||||||
struct D12FrameFormat
|
struct D12FrameFormat
|
||||||
{
|
{
|
||||||
D3D12_RESOURCE_DESC desc = {};
|
D3D12_RESOURCE_DESC desc = {};
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContex
|
|||||||
{
|
{
|
||||||
m_resPool.Init(dx11Device, dx12Device);
|
m_resPool.Init(dx11Device, dx12Device);
|
||||||
m_fbPool.Init(this);
|
m_fbPool.Init(this);
|
||||||
if (!m_postProcessor.Init(dx12Device))
|
if (m_dx11Device->IsSoftware())
|
||||||
|
DEBUG_INFO("Software render adapter: post-processing disabled");
|
||||||
|
else if (!m_postProcessor.Init(dx12Device))
|
||||||
DEBUG_ERROR("Failed to initialize post processor");
|
DEBUG_ERROR("Failed to initialize post processor");
|
||||||
|
|
||||||
// Manual-reset: both worker threads wait on this, so it must stay signalled
|
// Manual-reset: both worker threads wait on this, so it must stay signalled
|
||||||
@@ -189,7 +191,7 @@ bool CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
UINT sdrWhiteLevel = KVMFR_SDR_WHITE_LEVEL_DEFAULT;
|
UINT sdrWhiteLevel = KVMFR_SDR_WHITE_LEVEL_DEFAULT;
|
||||||
|
|
||||||
#ifdef HAS_IDDCX_110
|
#ifdef HAS_IDDCX_110
|
||||||
if (m_devContext->CanProcessFP16())
|
if (m_devContext->HasIddCx110DDIs())
|
||||||
{
|
{
|
||||||
IDARG_IN_RELEASEANDACQUIREBUFFER2 acquireIn = {};
|
IDARG_IN_RELEASEANDACQUIREBUFFER2 acquireIn = {};
|
||||||
acquireIn.Size = sizeof(acquireIn);
|
acquireIn.Size = sizeof(acquireIn);
|
||||||
@@ -780,7 +782,7 @@ bool CSwapChainProcessor::QueryHWCursor()
|
|||||||
UINT cursorWhiteLevel = m_sdrWhiteLevel.load(std::memory_order_relaxed);
|
UINT cursorWhiteLevel = m_sdrWhiteLevel.load(std::memory_order_relaxed);
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
#ifdef HAS_IDDCX_110
|
#ifdef HAS_IDDCX_110
|
||||||
if (m_devContext->CanProcessFP16())
|
if (m_devContext->HasIddCx110DDIs())
|
||||||
{
|
{
|
||||||
IDARG_OUT_QUERY_HWCURSOR3 out3 = {};
|
IDARG_OUT_QUERY_HWCURSOR3 out3 = {};
|
||||||
status = IddCxMonitorQueryHardwareCursor3(m_monitor, &in, &out3);
|
status = IddCxMonitorQueryHardwareCursor3(m_monitor, &in, &out3);
|
||||||
|
|||||||
@@ -160,13 +160,20 @@ NTSTATUS LGIddParseMonitorDescription2(const IDARG_IN_PARSEMONITORDESCRIPTION2*
|
|||||||
NTSTATUS LGIddAdapterQueryTargetInfo(IDDCX_ADAPTER adapter,
|
NTSTATUS LGIddAdapterQueryTargetInfo(IDDCX_ADAPTER adapter,
|
||||||
IDARG_IN_QUERYTARGET_INFO* inArgs, IDARG_OUT_QUERYTARGET_INFO* outArgs)
|
IDARG_IN_QUERYTARGET_INFO* inArgs, IDARG_OUT_QUERYTARGET_INFO* outArgs)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(adapter);
|
|
||||||
UNREFERENCED_PARAMETER(inArgs);
|
UNREFERENCED_PARAMETER(inArgs);
|
||||||
|
|
||||||
outArgs->TargetCaps =
|
auto* wrapper = WdfObjectGet_CIndirectDeviceContextWrapper(adapter);
|
||||||
(IDDCX_TARGET_CAPS)(IDDCX_TARGET_CAPS_WIDE_COLOR_SPACE | IDDCX_TARGET_CAPS_HIGH_COLOR_SPACE);
|
const bool hdr = wrapper && wrapper->context &&
|
||||||
outArgs->DitheringSupport.Rgb =
|
wrapper->context->CanProcessFP16();
|
||||||
(IDDCX_BITS_PER_COMPONENT)(IDDCX_BITS_PER_COMPONENT_8 | IDDCX_BITS_PER_COMPONENT_10);
|
|
||||||
|
outArgs->TargetCaps = hdr ?
|
||||||
|
(IDDCX_TARGET_CAPS)(IDDCX_TARGET_CAPS_WIDE_COLOR_SPACE |
|
||||||
|
IDDCX_TARGET_CAPS_HIGH_COLOR_SPACE) :
|
||||||
|
(IDDCX_TARGET_CAPS)0;
|
||||||
|
outArgs->DitheringSupport.Rgb = hdr ?
|
||||||
|
(IDDCX_BITS_PER_COMPONENT)(IDDCX_BITS_PER_COMPONENT_8 |
|
||||||
|
IDDCX_BITS_PER_COMPONENT_10) :
|
||||||
|
IDDCX_BITS_PER_COMPONENT_8;
|
||||||
outArgs->DitheringSupport.YCbCr444 = IDDCX_BITS_PER_COMPONENT_NONE;
|
outArgs->DitheringSupport.YCbCr444 = IDDCX_BITS_PER_COMPONENT_NONE;
|
||||||
outArgs->DitheringSupport.YCbCr422 = IDDCX_BITS_PER_COMPONENT_NONE;
|
outArgs->DitheringSupport.YCbCr422 = IDDCX_BITS_PER_COMPONENT_NONE;
|
||||||
outArgs->DitheringSupport.YCbCr420 = IDDCX_BITS_PER_COMPONENT_NONE;
|
outArgs->DitheringSupport.YCbCr420 = IDDCX_BITS_PER_COMPONENT_NONE;
|
||||||
@@ -187,6 +194,12 @@ NTSTATUS LGIddMonitorSetDefaultHdrMetadata(IDDCX_MONITOR monitor,
|
|||||||
auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
|
auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
|
||||||
auto* ctx = wrapper->context->GetDeviceContext();
|
auto* ctx = wrapper->context->GetDeviceContext();
|
||||||
|
|
||||||
|
if (ctx->IsSoftwareMode())
|
||||||
|
{
|
||||||
|
ctx->SetHDRActive(nullptr);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->SetHDRActive(inArgs->Data.pHdr10);
|
ctx->SetHDRActive(inArgs->Data.pHdr10);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@@ -197,6 +210,13 @@ NTSTATUS LGIddMonitorSetGammaRamp(IDDCX_MONITOR monitor, const IDARG_IN_SET_GAMM
|
|||||||
auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
|
auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
|
||||||
auto* ctx = wrapper->context->GetDeviceContext();
|
auto* ctx = wrapper->context->GetDeviceContext();
|
||||||
|
|
||||||
|
if (ctx->IsSoftwareMode())
|
||||||
|
{
|
||||||
|
ctx->SetColorTransform(nullptr);
|
||||||
|
DEBUG_INFO("Ignoring display color transform in software mode");
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (inArgs->Type == IDDCX_GAMMARAMP_TYPE_DEFAULT)
|
if (inArgs->Type == IDDCX_GAMMARAMP_TYPE_DEFAULT)
|
||||||
{
|
{
|
||||||
ctx->SetColorTransform(nullptr);
|
ctx->SetColorTransform(nullptr);
|
||||||
@@ -236,6 +256,13 @@ NTSTATUS LGIddMonitorSetGammaRamp(IDDCX_MONITOR monitor, const IDARG_IN_SET_GAMM
|
|||||||
transform->lut[i][3] = 1.0f;
|
transform->lut[i][3] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsIdentityColorTransform(*transform))
|
||||||
|
{
|
||||||
|
ctx->SetColorTransform(nullptr);
|
||||||
|
DEBUG_INFO("Ignoring identity display color transform");
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->SetColorTransform(std::move(transform));
|
ctx->SetColorTransform(std::move(transform));
|
||||||
DEBUG_INFO("Display color transform updated (matrix:%d lut:%d)",
|
DEBUG_INFO("Display color transform updated (matrix:%d lut:%d)",
|
||||||
input->MatrixEnabled, input->LutEnabled);
|
input->MatrixEnabled, input->LutEnabled);
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ PostProcessStatus CColorTransformEffect::SetFormat(
|
|||||||
const ComPtr<ID3D12Device3>& device,
|
const ComPtr<ID3D12Device3>& device,
|
||||||
const D12FrameFormat& src, D12FrameFormat& dst)
|
const D12FrameFormat& src, D12FrameFormat& dst)
|
||||||
{
|
{
|
||||||
if (!src.colorTransform ||
|
if (!src.colorTransform || IsIdentityColorTransform(*src.colorTransform) ||
|
||||||
(!src.colorTransform->matrixEnabled && !src.colorTransform->lutEnabled))
|
(!src.colorTransform->matrixEnabled && !src.colorTransform->lutEnabled))
|
||||||
return PostProcessStatus::BYPASS_EFFECT;
|
return PostProcessStatus::BYPASS_EFFECT;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user