1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-05 19:46:15 +01:00
dxvk/src/dxgi/dxgi_adapter.cpp

248 lines
7.1 KiB
C++
Raw Normal View History

2017-10-11 03:09:04 +02:00
#include <cstdlib>
#include <cstring>
#include <d3d10_1.h>
2017-10-11 03:09:04 +02:00
#include "dxgi_adapter.h"
#include "dxgi_device.h"
#include "dxgi_enums.h"
2017-10-11 03:09:04 +02:00
#include "dxgi_factory.h"
#include "dxgi_format.h"
2017-10-11 03:09:04 +02:00
#include "dxgi_output.h"
#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),
m_adapter (adapter),
m_formats (adapter) {
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
}
HRESULT STDMETHODCALLTYPE DxgiAdapter::QueryInterface(REFIID riid, void** ppvObject) {
*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");
Logger::warn(str::format(riid));
2017-10-11 03:09:04 +02:00
return E_NOINTERFACE;
}
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(
REFGUID InterfaceName,
LARGE_INTEGER* pUMDVersion) {
if (pUMDVersion != nullptr)
*pUMDVersion = LARGE_INTEGER();
if (InterfaceName == __uuidof(ID3D10Device)
|| InterfaceName == __uuidof(ID3D10Device1)) {
Logger::warn("DXGI: CheckInterfaceSupport: No D3D10 support");
if (env::getEnvVar(L"DXVK_FAKE_DX10_SUPPORT") == "1")
return S_OK;
}
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(
UINT Output,
IDXGIOutput** ppOutput) {
InitReturnPtr(ppOutput);
2017-10-11 03:09:04 +02:00
if (ppOutput == nullptr)
return DXGI_ERROR_INVALID_CALL;
if (Output > 0) {
*ppOutput = nullptr;
2017-10-11 03:09:04 +02:00
return DXGI_ERROR_NOT_FOUND;
}
2017-10-11 03:09:04 +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) {
if (pDesc == nullptr)
return DXGI_ERROR_INVALID_CALL;
DXGI_ADAPTER_DESC1 desc1;
HRESULT hr = this->GetDesc1(&desc1);
if (SUCCEEDED(hr)) {
std::memcpy(
pDesc->Description,
desc1.Description,
sizeof(pDesc->Description));
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();
// 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));
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;
}
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
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;
}
HRESULT STDMETHODCALLTYPE DxgiAdapter::CreateDevice(
IDXGIObject* pContainer,
const VkPhysicalDeviceFeatures* pFeatures,
IDXGIVkDevice** ppDevice) {
InitReturnPtr(ppDevice);
try {
*ppDevice = new dxvk::DxgiDevice(pContainer, this, pFeatures);
return S_OK;
} catch (const dxvk::DxvkError& e) {
dxvk::Logger::err(e.message());
return DXGI_ERROR_UNSUPPORTED;
}
}
DXGI_VK_FORMAT_INFO STDMETHODCALLTYPE DxgiAdapter::LookupFormat(
DXGI_FORMAT Format,
DXGI_VK_FORMAT_MODE Mode) {
return m_formats.GetFormatInfo(Format, Mode);
}
HRESULT DxgiAdapter::GetOutputFromMonitor(
HMONITOR Monitor,
IDXGIOutput** ppOutput) {
if (ppOutput == nullptr)
return DXGI_ERROR_INVALID_CALL;
for (uint32_t i = 0; SUCCEEDED(EnumOutputs(i, ppOutput)); i++) {
DXGI_OUTPUT_DESC outputDesc;
(*ppOutput)->GetDesc(&outputDesc);
if (outputDesc.Monitor == Monitor)
return S_OK;
(*ppOutput)->Release();
(*ppOutput) = nullptr;
}
// No such output found
return DXGI_ERROR_NOT_FOUND;
}
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
}