2017-10-11 03:09:04 +02:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
|
2018-05-02 17:00:56 +02:00
|
|
|
#include <d3d10_1.h>
|
|
|
|
|
2017-10-11 03:09:04 +02:00
|
|
|
#include "dxgi_adapter.h"
|
2018-03-28 18:58:53 +02:00
|
|
|
#include "dxgi_device.h"
|
2017-12-04 11:33:04 +01:00
|
|
|
#include "dxgi_enums.h"
|
2017-10-11 03:09:04 +02:00
|
|
|
#include "dxgi_factory.h"
|
2018-04-12 17:49:14 +02:00
|
|
|
#include "dxgi_format.h"
|
2017-10-11 03:09:04 +02:00
|
|
|
#include "dxgi_output.h"
|
|
|
|
|
2017-12-04 11:33:04 +01:00
|
|
|
#include "../dxvk/vulkan/dxvk_vulkan_names.h"
|
|
|
|
|
2017-10-11 03:09:04 +02:00
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
DxgiAdapter::DxgiAdapter(
|
|
|
|
DxgiFactory* factory,
|
|
|
|
const Rc<DxvkAdapter>& adapter)
|
|
|
|
: m_factory (factory),
|
2018-05-06 13:12:30 +02:00
|
|
|
m_adapter (adapter),
|
|
|
|
m_formats (adapter) {
|
2018-04-12 17:49:14 +02:00
|
|
|
|
2017-10-11 03:09:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxgiAdapter::~DxgiAdapter() {
|
2017-11-26 14:01:41 +01:00
|
|
|
|
2017-10-11 03:09:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-28 21:24:52 +02:00
|
|
|
HRESULT STDMETHODCALLTYPE DxgiAdapter::QueryInterface(REFIID riid, void** ppvObject) {
|
2018-04-02 12:52:02 +02:00
|
|
|
*ppvObject = nullptr;
|
|
|
|
|
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|
|
|| riid == __uuidof(IDXGIObject)
|
|
|
|
|| riid == __uuidof(IDXGIAdapter)
|
|
|
|
|| riid == __uuidof(IDXGIAdapter1)
|
|
|
|
|| riid == __uuidof(IDXGIVkAdapter)) {
|
|
|
|
*ppvObject = ref(this);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2017-10-11 03:09:04 +02:00
|
|
|
|
|
|
|
Logger::warn("DxgiAdapter::QueryInterface: Unknown interface query");
|
2018-03-12 12:05:43 +01:00
|
|
|
Logger::warn(str::format(riid));
|
2017-10-11 03:09:04 +02:00
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-28 21:24:52 +02:00
|
|
|
HRESULT STDMETHODCALLTYPE DxgiAdapter::GetParent(REFIID riid, void** ppParent) {
|
2017-10-11 03:09:04 +02:00
|
|
|
return m_factory->QueryInterface(riid, ppParent);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE DxgiAdapter::CheckInterfaceSupport(
|
2018-04-12 13:38:22 +02:00
|
|
|
REFGUID InterfaceName,
|
|
|
|
LARGE_INTEGER* pUMDVersion) {
|
2018-04-30 20:01:50 +02:00
|
|
|
if (pUMDVersion != nullptr)
|
|
|
|
*pUMDVersion = LARGE_INTEGER();
|
|
|
|
|
2018-05-02 17:00:56 +02:00
|
|
|
if (InterfaceName == __uuidof(ID3D10Device)
|
|
|
|
|| InterfaceName == __uuidof(ID3D10Device1)) {
|
|
|
|
Logger::warn("DXGI: CheckInterfaceSupport: No D3D10 support");
|
2018-05-05 00:48:35 +02:00
|
|
|
|
|
|
|
if (env::getEnvVar(L"DXVK_FAKE_DX10_SUPPORT") == "1")
|
|
|
|
return S_OK;
|
2018-05-02 17:00:56 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 20:01:50 +02:00
|
|
|
Logger::err("DXGI: CheckInterfaceSupport: Unsupported interface");
|
|
|
|
Logger::err(str::format(InterfaceName));
|
2017-10-11 03:09:04 +02:00
|
|
|
return DXGI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE DxgiAdapter::EnumOutputs(
|
2018-04-12 13:38:22 +02:00
|
|
|
UINT Output,
|
|
|
|
IDXGIOutput** ppOutput) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppOutput);
|
|
|
|
|
2017-10-11 03:09:04 +02:00
|
|
|
if (ppOutput == nullptr)
|
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
|
2018-04-12 01:48:57 +02:00
|
|
|
if (Output > 0) {
|
|
|
|
*ppOutput = nullptr;
|
2017-10-11 03:09:04 +02:00
|
|
|
return DXGI_ERROR_NOT_FOUND;
|
2018-04-12 01:48:57 +02:00
|
|
|
}
|
2017-10-11 03:09:04 +02:00
|
|
|
|
2018-04-12 01:48:57 +02:00
|
|
|
// TODO support multiple monitors
|
|
|
|
HMONITOR monitor = ::MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
|
|
|
*ppOutput = ref(new DxgiOutput(this, monitor));
|
2017-10-11 03:09:04 +02:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc(DXGI_ADAPTER_DESC* pDesc) {
|
2018-03-26 07:38:37 +02:00
|
|
|
if (pDesc == nullptr)
|
2018-03-28 11:56:58 +02:00
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
2018-03-26 07:38:37 +02:00
|
|
|
|
2017-11-26 16:12:11 +01:00
|
|
|
DXGI_ADAPTER_DESC1 desc1;
|
|
|
|
HRESULT hr = this->GetDesc1(&desc1);
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr)) {
|
2017-11-26 16:18:32 +01:00
|
|
|
std::memcpy(
|
|
|
|
pDesc->Description,
|
|
|
|
desc1.Description,
|
|
|
|
sizeof(pDesc->Description));
|
|
|
|
|
2017-11-26 16:12:11 +01:00
|
|
|
pDesc->VendorId = desc1.VendorId;
|
|
|
|
pDesc->DeviceId = desc1.DeviceId;
|
|
|
|
pDesc->SubSysId = desc1.SubSysId;
|
|
|
|
pDesc->Revision = desc1.Revision;
|
|
|
|
pDesc->DedicatedVideoMemory = desc1.DedicatedVideoMemory;
|
|
|
|
pDesc->DedicatedSystemMemory = desc1.DedicatedSystemMemory;
|
|
|
|
pDesc->SharedSystemMemory = desc1.SharedSystemMemory;
|
|
|
|
pDesc->AdapterLuid = desc1.AdapterLuid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc1(DXGI_ADAPTER_DESC1* pDesc) {
|
2017-10-11 03:09:04 +02:00
|
|
|
if (pDesc == nullptr)
|
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
|
2018-03-17 00:40:26 +01:00
|
|
|
auto deviceProp = m_adapter->deviceProperties();
|
|
|
|
auto memoryProp = m_adapter->memoryProperties();
|
|
|
|
|
2018-03-28 21:24:52 +02:00
|
|
|
// Custom Vendor ID
|
2018-03-17 00:40:26 +01:00
|
|
|
const std::string customVendorID = env::getEnvVar(L"DXVK_CUSTOM_VENDOR_ID");
|
|
|
|
const std::string customDeviceID = env::getEnvVar(L"DXVK_CUSTOM_DEVICE_ID");
|
|
|
|
|
|
|
|
if (!customVendorID.empty()) {
|
|
|
|
Logger::info("Using Custom PCI Vendor ID " + customVendorID + " instead of " + str::format(std::hex, deviceProp.vendorID));
|
|
|
|
deviceProp.vendorID = std::stoul(customVendorID, nullptr, 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!customDeviceID.empty()) {
|
|
|
|
Logger::info("Using Custom PCI Device ID " + customDeviceID + " instead of " + str::format(std::hex, deviceProp.deviceID));
|
|
|
|
deviceProp.deviceID = std::stoul(customDeviceID, nullptr, 16);
|
|
|
|
}
|
2017-10-11 03:09:04 +02:00
|
|
|
|
|
|
|
std::memset(pDesc->Description, 0, sizeof(pDesc->Description));
|
2018-04-02 18:49:03 +02:00
|
|
|
std::mbstowcs(pDesc->Description, deviceProp.deviceName, std::size(pDesc->Description) - 1);
|
2017-10-11 03:09:04 +02:00
|
|
|
|
|
|
|
VkDeviceSize deviceMemory = 0;
|
|
|
|
VkDeviceSize sharedMemory = 0;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < memoryProp.memoryHeapCount; i++) {
|
|
|
|
VkMemoryHeap heap = memoryProp.memoryHeaps[i];
|
|
|
|
|
|
|
|
if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
|
|
|
|
deviceMemory += heap.size;
|
|
|
|
else
|
|
|
|
sharedMemory += heap.size;
|
|
|
|
}
|
|
|
|
|
2018-05-07 19:04:25 +02:00
|
|
|
#ifndef _WIN64
|
|
|
|
// The value returned by DXGI is a 32-bit value
|
|
|
|
// on 32-bit platforms, so we need to clamp it
|
|
|
|
VkDeviceSize maxMemory = 0xF0000000;
|
|
|
|
deviceMemory = std::min(deviceMemory, maxMemory);
|
|
|
|
sharedMemory = std::min(sharedMemory, maxMemory);
|
|
|
|
#endif
|
|
|
|
|
2017-10-11 03:09:04 +02:00
|
|
|
pDesc->VendorId = deviceProp.vendorID;
|
|
|
|
pDesc->DeviceId = deviceProp.deviceID;
|
|
|
|
pDesc->SubSysId = 0;
|
|
|
|
pDesc->Revision = 0;
|
|
|
|
pDesc->DedicatedVideoMemory = deviceMemory;
|
|
|
|
pDesc->DedicatedSystemMemory = 0;
|
|
|
|
pDesc->SharedSystemMemory = sharedMemory;
|
|
|
|
pDesc->AdapterLuid = LUID { 0, 0 }; // TODO implement
|
2017-11-26 16:12:11 +01:00
|
|
|
pDesc->Flags = 0;
|
2017-10-11 03:09:04 +02:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2017-10-11 15:31:36 +02:00
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
Rc<DxvkAdapter> STDMETHODCALLTYPE DxgiAdapter::GetDXVKAdapter() {
|
2017-10-11 15:31:36 +02:00
|
|
|
return m_adapter;
|
|
|
|
}
|
|
|
|
|
2017-12-04 11:33:04 +01:00
|
|
|
|
2018-03-28 18:58:53 +02:00
|
|
|
HRESULT STDMETHODCALLTYPE DxgiAdapter::CreateDevice(
|
2018-03-28 21:24:52 +02:00
|
|
|
IDXGIObject* pContainer,
|
2018-03-28 18:58:53 +02:00
|
|
|
const VkPhysicalDeviceFeatures* pFeatures,
|
2018-03-28 21:24:52 +02:00
|
|
|
IDXGIVkDevice** ppDevice) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppDevice);
|
|
|
|
|
2018-03-28 18:58:53 +02:00
|
|
|
try {
|
2018-03-28 21:24:52 +02:00
|
|
|
*ppDevice = new dxvk::DxgiDevice(pContainer, this, pFeatures);
|
2018-03-28 18:58:53 +02:00
|
|
|
return S_OK;
|
|
|
|
} catch (const dxvk::DxvkError& e) {
|
|
|
|
dxvk::Logger::err(e.message());
|
|
|
|
return DXGI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-12 15:36:01 +02:00
|
|
|
DXGI_VK_FORMAT_INFO STDMETHODCALLTYPE DxgiAdapter::LookupFormat(
|
2018-04-12 17:49:14 +02:00
|
|
|
DXGI_FORMAT Format,
|
|
|
|
DXGI_VK_FORMAT_MODE Mode) {
|
2018-05-06 13:12:30 +02:00
|
|
|
return m_formats.GetFormatInfo(Format, Mode);
|
2017-12-04 11:33:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-13 18:56:15 +01:00
|
|
|
HRESULT DxgiAdapter::GetOutputFromMonitor(
|
2018-04-12 13:38:22 +02:00
|
|
|
HMONITOR Monitor,
|
|
|
|
IDXGIOutput** ppOutput) {
|
2018-03-28 11:56:58 +02:00
|
|
|
if (ppOutput == nullptr)
|
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
2018-01-13 18:56:15 +01:00
|
|
|
|
2018-03-28 11:56:58 +02:00
|
|
|
for (uint32_t i = 0; SUCCEEDED(EnumOutputs(i, ppOutput)); i++) {
|
2018-01-13 18:56:15 +01:00
|
|
|
DXGI_OUTPUT_DESC outputDesc;
|
2018-03-28 11:56:58 +02:00
|
|
|
(*ppOutput)->GetDesc(&outputDesc);
|
2018-01-13 18:56:15 +01:00
|
|
|
|
2018-03-28 11:56:58 +02:00
|
|
|
if (outputDesc.Monitor == Monitor)
|
2018-01-13 18:56:15 +01:00
|
|
|
return S_OK;
|
2018-03-28 11:56:58 +02:00
|
|
|
|
|
|
|
(*ppOutput)->Release();
|
|
|
|
(*ppOutput) = nullptr;
|
2018-01-13 18:56:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// No such output found
|
|
|
|
return DXGI_ERROR_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-12 13:38:22 +02:00
|
|
|
HRESULT DxgiAdapter::GetOutputData(
|
|
|
|
HMONITOR Monitor,
|
|
|
|
DXGI_VK_OUTPUT_DATA* pOutputData) {
|
|
|
|
std::lock_guard<std::mutex> lock(m_outputMutex);
|
|
|
|
|
|
|
|
auto entry = m_outputData.find(Monitor);
|
|
|
|
if (entry == m_outputData.end())
|
|
|
|
return DXGI_ERROR_NOT_FOUND;
|
|
|
|
|
|
|
|
if (pOutputData == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
*pOutputData = entry->second;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT DxgiAdapter::SetOutputData(
|
|
|
|
HMONITOR Monitor,
|
|
|
|
const DXGI_VK_OUTPUT_DATA* pOutputData) {
|
|
|
|
std::lock_guard<std::mutex> lock(m_outputMutex);
|
|
|
|
|
|
|
|
m_outputData.insert_or_assign(Monitor, *pOutputData);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2017-10-11 03:09:04 +02:00
|
|
|
}
|