2017-12-21 07:45:38 +08:00
|
|
|
/*
|
2019-12-30 21:40:24 +08:00
|
|
|
* Copyright (C) 2018-2020 Intel Corporation
|
2017-12-21 07:45:38 +08:00
|
|
|
*
|
2018-09-18 15:11:08 +08:00
|
|
|
* SPDX-License-Identifier: MIT
|
2017-12-21 07:45:38 +08:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-02-24 05:44:01 +08:00
|
|
|
#include "shared/source/os_interface/windows/wddm/wddm.h"
|
|
|
|
|
|
|
|
#include "shared/source/command_stream/preemption.h"
|
|
|
|
#include "shared/source/execution_environment/root_device_environment.h"
|
|
|
|
#include "shared/source/gmm_helper/gmm.h"
|
|
|
|
#include "shared/source/gmm_helper/gmm_helper.h"
|
|
|
|
#include "shared/source/gmm_helper/page_table_mngr.h"
|
|
|
|
#include "shared/source/gmm_helper/resource_info.h"
|
|
|
|
#include "shared/source/helpers/interlocked_max.h"
|
|
|
|
#include "shared/source/helpers/windows/gmm_callbacks.h"
|
|
|
|
#include "shared/source/os_interface/hw_info_config.h"
|
|
|
|
#include "shared/source/os_interface/windows/debug_registry_reader.h"
|
2020-03-17 18:55:53 +08:00
|
|
|
#include "shared/source/os_interface/windows/driver_info_windows.h"
|
2020-02-24 05:44:01 +08:00
|
|
|
#include "shared/source/os_interface/windows/gdi_interface.h"
|
|
|
|
#include "shared/source/os_interface/windows/kmdaf_listener.h"
|
|
|
|
#include "shared/source/os_interface/windows/os_context_win.h"
|
2020-03-17 14:26:46 +08:00
|
|
|
#include "shared/source/os_interface/windows/os_environment_win.h"
|
2020-02-24 05:44:01 +08:00
|
|
|
#include "shared/source/os_interface/windows/os_interface.h"
|
|
|
|
#include "shared/source/os_interface/windows/wddm/wddm_interface.h"
|
2020-03-17 19:19:38 +08:00
|
|
|
#include "shared/source/os_interface/windows/wddm/wddm_residency_logger.h"
|
2020-02-24 05:44:01 +08:00
|
|
|
#include "shared/source/os_interface/windows/wddm_allocation.h"
|
|
|
|
#include "shared/source/os_interface/windows/wddm_engine_mapper.h"
|
|
|
|
#include "shared/source/os_interface/windows/wddm_residency_allocations_container.h"
|
|
|
|
#include "shared/source/sku_info/operations/windows/sku_info_receiver.h"
|
|
|
|
#include "shared/source/utilities/stackvec.h"
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2019-02-27 18:39:32 +08:00
|
|
|
#include "gmm_memory.h"
|
|
|
|
|
2020-01-27 20:59:19 +08:00
|
|
|
#include <dxgi.h>
|
|
|
|
|
2019-03-26 18:59:46 +08:00
|
|
|
namespace NEO {
|
2017-12-21 07:45:38 +08:00
|
|
|
extern Wddm::CreateDXGIFactoryFcn getCreateDxgiFactory();
|
|
|
|
extern Wddm::GetSystemInfoFcn getGetSystemInfo();
|
2018-03-22 17:38:23 +08:00
|
|
|
extern Wddm::VirtualAllocFcn getVirtualAlloc();
|
|
|
|
extern Wddm::VirtualFreeFcn getVirtualFree();
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
Wddm::CreateDXGIFactoryFcn Wddm::createDxgiFactory = getCreateDxgiFactory();
|
|
|
|
Wddm::GetSystemInfoFcn Wddm::getSystemInfo = getGetSystemInfo();
|
2018-03-22 17:38:23 +08:00
|
|
|
Wddm::VirtualAllocFcn Wddm::virtualAllocFnc = getVirtualAlloc();
|
|
|
|
Wddm::VirtualFreeFcn Wddm::virtualFreeFnc = getVirtualFree();
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2020-02-07 17:29:56 +08:00
|
|
|
Wddm::Wddm(std::unique_ptr<HwDeviceId> hwDeviceIdIn, RootDeviceEnvironment &rootDeviceEnvironment) : hwDeviceId(std::move(hwDeviceIdIn)), rootDeviceEnvironment(rootDeviceEnvironment) {
|
|
|
|
UNRECOVERABLE_IF(!hwDeviceId);
|
2018-03-03 04:43:37 +08:00
|
|
|
featureTable.reset(new FeatureTable());
|
2019-05-08 22:00:24 +08:00
|
|
|
workaroundTable.reset(new WorkaroundTable());
|
2018-03-03 04:43:37 +08:00
|
|
|
gtSystemInfo.reset(new GT_SYSTEM_INFO);
|
|
|
|
gfxPlatform.reset(new PLATFORM);
|
|
|
|
memset(gtSystemInfo.get(), 0, sizeof(*gtSystemInfo));
|
|
|
|
memset(gfxPlatform.get(), 0, sizeof(*gfxPlatform));
|
2019-11-07 01:14:30 +08:00
|
|
|
this->registryReader.reset(new RegistryReader(false, "System\\CurrentControlSet\\Control\\GraphicsDrivers\\Scheduler"));
|
2018-01-31 18:22:13 +08:00
|
|
|
kmDafListener = std::unique_ptr<KmDafListener>(new KmDafListener);
|
2019-07-12 22:50:14 +08:00
|
|
|
temporaryResources = std::make_unique<WddmResidentAllocationsContainer>(this);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Wddm::~Wddm() {
|
2019-10-30 21:25:58 +08:00
|
|
|
temporaryResources.reset();
|
2017-12-21 07:45:38 +08:00
|
|
|
destroyPagingQueue();
|
|
|
|
destroyDevice();
|
2019-11-12 21:29:39 +08:00
|
|
|
UNRECOVERABLE_IF(temporaryResources.get())
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2020-02-10 18:15:34 +08:00
|
|
|
bool Wddm::init() {
|
2018-08-10 17:07:17 +08:00
|
|
|
if (!queryAdapterInfo()) {
|
2018-06-12 15:42:47 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-10 17:07:17 +08:00
|
|
|
auto productFamily = gfxPlatform->eProductFamily;
|
2018-06-12 15:42:47 +08:00
|
|
|
if (!hardwareInfoTable[productFamily]) {
|
|
|
|
return false;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2020-02-10 18:15:34 +08:00
|
|
|
auto hardwareInfo = std::make_unique<HardwareInfo>();
|
|
|
|
hardwareInfo->platform = *gfxPlatform;
|
|
|
|
hardwareInfo->featureTable = *featureTable;
|
|
|
|
hardwareInfo->workaroundTable = *workaroundTable;
|
|
|
|
hardwareInfo->gtSystemInfo = *gtSystemInfo;
|
2018-02-28 23:52:08 +08:00
|
|
|
|
2020-02-10 18:15:34 +08:00
|
|
|
hardwareInfo->capabilityTable = hardwareInfoTable[productFamily]->capabilityTable;
|
|
|
|
hardwareInfo->capabilityTable.maxRenderFrequency = maxRenderFrequency;
|
|
|
|
hardwareInfo->capabilityTable.instrumentationEnabled =
|
|
|
|
(hardwareInfo->capabilityTable.instrumentationEnabled && instrumentationEnabled);
|
2018-04-05 00:38:36 +08:00
|
|
|
|
2018-06-12 15:42:47 +08:00
|
|
|
HwInfoConfig *hwConfig = HwInfoConfig::get(productFamily);
|
2019-07-08 19:30:31 +08:00
|
|
|
|
2020-02-10 18:15:34 +08:00
|
|
|
hwConfig->adjustPlatformForProductFamily(hardwareInfo.get());
|
|
|
|
if (hwConfig->configureHwInfo(hardwareInfo.get(), hardwareInfo.get(), nullptr)) {
|
2019-07-08 19:30:31 +08:00
|
|
|
return false;
|
|
|
|
}
|
2018-06-12 15:42:47 +08:00
|
|
|
|
2020-02-10 18:15:34 +08:00
|
|
|
auto preemptionMode = PreemptionHelper::getDefaultPreemptionMode(*hardwareInfo);
|
2020-03-04 15:51:02 +08:00
|
|
|
rootDeviceEnvironment.setHwInfo(hardwareInfo.get());
|
2020-02-25 23:38:47 +08:00
|
|
|
rootDeviceEnvironment.initGmm();
|
2019-07-11 00:35:06 +08:00
|
|
|
|
2019-12-17 21:29:28 +08:00
|
|
|
if (WddmVersion::WDDM_2_3 == getWddmVersion()) {
|
2019-07-08 19:30:31 +08:00
|
|
|
wddmInterface = std::make_unique<WddmInterface23>(*this);
|
|
|
|
} else {
|
|
|
|
wddmInterface = std::make_unique<WddmInterface20>(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!createDevice(preemptionMode)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!createPagingQueue()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!gmmMemory) {
|
2020-02-25 01:04:30 +08:00
|
|
|
gmmMemory.reset(GmmMemory::create(rootDeviceEnvironment.getGmmClientContext()));
|
2019-07-08 19:30:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return configureDeviceAddressSpace();
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::queryAdapterInfo() {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_QUERYADAPTERINFO QueryAdapterInfo = {0};
|
2018-03-03 04:43:37 +08:00
|
|
|
ADAPTER_INFO adapterInfo = {0};
|
2020-02-05 17:49:54 +08:00
|
|
|
QueryAdapterInfo.hAdapter = getAdapter();
|
2017-12-21 07:45:38 +08:00
|
|
|
QueryAdapterInfo.Type = KMTQAITYPE_UMDRIVERPRIVATE;
|
2018-03-03 04:43:37 +08:00
|
|
|
QueryAdapterInfo.pPrivateDriverData = &adapterInfo;
|
2017-12-21 07:45:38 +08:00
|
|
|
QueryAdapterInfo.PrivateDriverDataSize = sizeof(ADAPTER_INFO);
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->queryAdapterInfo(&QueryAdapterInfo);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
|
|
|
// translate
|
|
|
|
if (status == STATUS_SUCCESS) {
|
2018-03-03 04:43:37 +08:00
|
|
|
memcpy_s(gtSystemInfo.get(), sizeof(GT_SYSTEM_INFO), &adapterInfo.SystemInfo, sizeof(GT_SYSTEM_INFO));
|
|
|
|
memcpy_s(gfxPlatform.get(), sizeof(PLATFORM), &adapterInfo.GfxPlatform, sizeof(PLATFORM));
|
|
|
|
|
|
|
|
SkuInfoReceiver::receiveFtrTableFromAdapterInfo(featureTable.get(), &adapterInfo);
|
2019-05-08 22:00:24 +08:00
|
|
|
SkuInfoReceiver::receiveWaTableFromAdapterInfo(workaroundTable.get(), &adapterInfo);
|
2018-03-03 04:43:37 +08:00
|
|
|
|
|
|
|
memcpy_s(&gfxPartition, sizeof(gfxPartition), &adapterInfo.GfxPartition, sizeof(GMM_GFX_PARTITIONING));
|
2019-10-15 21:05:47 +08:00
|
|
|
memcpy_s(&adapterBDF, sizeof(adapterBDF), &adapterInfo.stAdapterBDF, sizeof(ADAPTER_BDF));
|
2018-03-03 04:43:37 +08:00
|
|
|
|
|
|
|
deviceRegistryPath = adapterInfo.DeviceRegistryPath;
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-03-03 04:43:37 +08:00
|
|
|
systemSharedMemory = adapterInfo.SystemSharedMemory;
|
2019-07-29 20:32:37 +08:00
|
|
|
dedicatedVideoMemory = adapterInfo.DedicatedVideoMemory;
|
2018-03-03 04:43:37 +08:00
|
|
|
maxRenderFrequency = adapterInfo.MaxRenderFreq;
|
|
|
|
instrumentationEnabled = adapterInfo.Caps.InstrumentationIsEnabled != 0;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::createPagingQueue() {
|
|
|
|
D3DKMT_CREATEPAGINGQUEUE CreatePagingQueue = {0};
|
|
|
|
CreatePagingQueue.hDevice = device;
|
|
|
|
CreatePagingQueue.Priority = D3DDDI_PAGINGQUEUE_PRIORITY_NORMAL;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
NTSTATUS status = getGdi()->createPagingQueue(&CreatePagingQueue);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
pagingQueue = CreatePagingQueue.hPagingQueue;
|
|
|
|
pagingQueueSyncObject = CreatePagingQueue.hSyncObject;
|
|
|
|
pagingFenceAddress = reinterpret_cast<UINT64 *>(CreatePagingQueue.FenceValueCPUVirtualAddress);
|
2020-03-17 19:19:38 +08:00
|
|
|
createPagingFenceLogger();
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::destroyPagingQueue() {
|
|
|
|
D3DDDI_DESTROYPAGINGQUEUE DestroyPagingQueue = {0};
|
|
|
|
if (pagingQueue) {
|
|
|
|
DestroyPagingQueue.hPagingQueue = pagingQueue;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
NTSTATUS status = getGdi()->destroyPagingQueue(&DestroyPagingQueue);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
pagingQueue = 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-12-10 17:30:39 +08:00
|
|
|
bool Wddm::createDevice(PreemptionMode preemptionMode) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_CREATEDEVICE CreateDevice = {{0}};
|
2020-02-05 17:49:54 +08:00
|
|
|
if (hwDeviceId) {
|
|
|
|
CreateDevice.hAdapter = getAdapter();
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateDevice.Flags.LegacyMode = FALSE;
|
2018-02-06 18:58:05 +08:00
|
|
|
if (preemptionMode >= PreemptionMode::MidBatch) {
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateDevice.Flags.DisableGpuTimeout = readEnablePreemptionRegKey();
|
|
|
|
}
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->createDevice(&CreateDevice);
|
2017-12-21 07:45:38 +08:00
|
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
device = CreateDevice.hDevice;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::destroyDevice() {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_DESTROYDEVICE DestroyDevice = {0};
|
|
|
|
if (device) {
|
|
|
|
DestroyDevice.hDevice = device;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->destroyDevice(&DestroyDevice);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
device = 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-17 14:26:46 +08:00
|
|
|
std::unique_ptr<HwDeviceId> createHwDeviceIdFromAdapterLuid(OsEnvironmentWin &osEnvironment, LUID adapterLuid) {
|
2020-02-17 23:14:22 +08:00
|
|
|
D3DKMT_OPENADAPTERFROMLUID OpenAdapterData = {{0}};
|
|
|
|
OpenAdapterData.AdapterLuid = adapterLuid;
|
2020-03-17 14:26:46 +08:00
|
|
|
auto status = osEnvironment.gdi->openAdapterFromLuid(&OpenAdapterData);
|
2020-02-17 23:14:22 +08:00
|
|
|
|
2020-03-17 18:55:53 +08:00
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DEBUG_BREAK_IF("openAdapterFromLuid failed");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
D3DKMT_QUERYADAPTERINFO QueryAdapterInfo = {0};
|
|
|
|
ADAPTER_INFO adapterInfo = {0};
|
|
|
|
QueryAdapterInfo.hAdapter = OpenAdapterData.hAdapter;
|
|
|
|
QueryAdapterInfo.Type = KMTQAITYPE_UMDRIVERPRIVATE;
|
|
|
|
QueryAdapterInfo.pPrivateDriverData = &adapterInfo;
|
|
|
|
QueryAdapterInfo.PrivateDriverDataSize = sizeof(ADAPTER_INFO);
|
|
|
|
|
|
|
|
status = osEnvironment.gdi->queryAdapterInfo(&QueryAdapterInfo);
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DEBUG_BREAK_IF("queryAdapterInfo failed");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string deviceRegistryPath = adapterInfo.DeviceRegistryPath;
|
|
|
|
DriverInfoWindows driverInfo(std::move(deviceRegistryPath));
|
|
|
|
if (!driverInfo.isCompatibleDriverStore()) {
|
|
|
|
return nullptr;
|
2020-02-17 23:14:22 +08:00
|
|
|
}
|
2020-03-17 18:55:53 +08:00
|
|
|
|
|
|
|
return std::make_unique<HwDeviceId>(OpenAdapterData.hAdapter, adapterLuid, &osEnvironment);
|
2020-02-17 23:14:22 +08:00
|
|
|
}
|
|
|
|
|
2020-03-17 14:26:46 +08:00
|
|
|
std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionEnvironment &executionEnvironment) {
|
2020-02-17 23:14:22 +08:00
|
|
|
std::vector<std::unique_ptr<HwDeviceId>> hwDeviceIds;
|
2020-03-17 14:26:46 +08:00
|
|
|
|
|
|
|
auto osEnvironment = new OsEnvironmentWin();
|
|
|
|
auto gdi = osEnvironment->gdi.get();
|
|
|
|
executionEnvironment.osEnvironment.reset(osEnvironment);
|
2020-02-05 17:49:54 +08:00
|
|
|
|
|
|
|
if (!gdi->isInitialized()) {
|
2020-02-17 23:14:22 +08:00
|
|
|
return hwDeviceIds;
|
2020-02-05 17:49:54 +08:00
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
DXGI_ADAPTER_DESC1 OpenAdapterDesc = {{0}};
|
|
|
|
|
|
|
|
IDXGIFactory1 *pFactory = nullptr;
|
|
|
|
IDXGIAdapter1 *pAdapter = nullptr;
|
|
|
|
DWORD iDevNum = 0;
|
|
|
|
|
|
|
|
HRESULT hr = Wddm::createDxgiFactory(__uuidof(IDXGIFactory), (void **)(&pFactory));
|
|
|
|
if ((hr != S_OK) || (pFactory == nullptr)) {
|
2020-02-17 23:14:22 +08:00
|
|
|
return hwDeviceIds;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
while (pFactory->EnumAdapters1(iDevNum++, &pAdapter) != DXGI_ERROR_NOT_FOUND) {
|
|
|
|
hr = pAdapter->GetDesc1(&OpenAdapterDesc);
|
|
|
|
if (hr == S_OK) {
|
2020-02-17 23:14:22 +08:00
|
|
|
bool createHwDeviceId = false;
|
2017-12-21 07:45:38 +08:00
|
|
|
// Check for adapters that include either "Intel" or "Citrix" (which may
|
|
|
|
// be virtualizing one of our adapters) in the description
|
|
|
|
if ((wcsstr(OpenAdapterDesc.Description, L"Intel") != 0) ||
|
2020-02-12 19:34:39 +08:00
|
|
|
(wcsstr(OpenAdapterDesc.Description, L"Citrix") != 0) ||
|
|
|
|
(wcsstr(OpenAdapterDesc.Description, L"Virtual Render") != 0)) {
|
2019-09-13 18:14:06 +08:00
|
|
|
char deviceId[16];
|
|
|
|
sprintf_s(deviceId, "%X", OpenAdapterDesc.DeviceId);
|
2020-03-17 18:55:53 +08:00
|
|
|
createHwDeviceId = (DebugManager.flags.ForceDeviceId.get() == "unk") || (DebugManager.flags.ForceDeviceId.get() == deviceId);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2020-02-17 23:14:22 +08:00
|
|
|
if (createHwDeviceId) {
|
2020-03-17 14:26:46 +08:00
|
|
|
auto hwDeviceId = createHwDeviceIdFromAdapterLuid(*osEnvironment, OpenAdapterDesc.AdapterLuid);
|
2020-02-17 23:14:22 +08:00
|
|
|
if (hwDeviceId) {
|
|
|
|
hwDeviceIds.push_back(std::move(hwDeviceId));
|
|
|
|
}
|
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
// Release all the non-Intel adapters
|
|
|
|
pAdapter->Release();
|
|
|
|
pAdapter = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pAdapter != nullptr) {
|
|
|
|
pAdapter->Release();
|
|
|
|
pAdapter = nullptr;
|
|
|
|
}
|
|
|
|
if (pFactory != nullptr) {
|
|
|
|
pFactory->Release();
|
|
|
|
pFactory = nullptr;
|
|
|
|
}
|
2020-02-17 23:14:22 +08:00
|
|
|
size_t numRootDevices = 1u;
|
|
|
|
if (DebugManager.flags.CreateMultipleRootDevices.get()) {
|
|
|
|
numRootDevices = DebugManager.flags.CreateMultipleRootDevices.get();
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2020-02-17 23:14:22 +08:00
|
|
|
if (hwDeviceIds.empty()) {
|
|
|
|
return hwDeviceIds;
|
2020-02-05 17:49:54 +08:00
|
|
|
}
|
2020-02-17 23:14:22 +08:00
|
|
|
|
|
|
|
while (hwDeviceIds.size() < numRootDevices) {
|
2020-03-17 14:26:46 +08:00
|
|
|
hwDeviceIds.push_back(std::make_unique<HwDeviceId>(hwDeviceIds[0]->getAdapter(), hwDeviceIds[0]->getAdapterLuid(), osEnvironment));
|
2020-02-17 23:14:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return hwDeviceIds;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-03-05 21:21:57 +08:00
|
|
|
bool Wddm::evict(const D3DKMT_HANDLE *handleList, uint32_t numOfHandles, uint64_t &sizeToTrim) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DKMT_EVICT Evict = {0};
|
|
|
|
Evict.AllocationList = handleList;
|
|
|
|
Evict.hDevice = device;
|
|
|
|
Evict.NumAllocations = numOfHandles;
|
|
|
|
Evict.NumBytesToTrim = 0;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->evict(&Evict);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
sizeToTrim = Evict.NumBytesToTrim;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyEvict(featureTable->ftrKmdDaf, getAdapter(), device, handleList, numOfHandles, getGdi()->escape);
|
2018-01-31 18:22:13 +08:00
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-03-17 19:19:38 +08:00
|
|
|
bool Wddm::makeResident(const D3DKMT_HANDLE *handles, uint32_t count, bool cantTrimFurther, uint64_t *numberOfBytesToTrim, size_t totalSize) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DDDI_MAKERESIDENT makeResident = {0};
|
|
|
|
UINT priority = 0;
|
|
|
|
bool success = false;
|
|
|
|
|
2020-03-17 19:19:38 +08:00
|
|
|
perfLogResidencyReportAllocations(residencyLogger.get(), count, totalSize);
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
makeResident.AllocationList = handles;
|
|
|
|
makeResident.hPagingQueue = pagingQueue;
|
|
|
|
makeResident.NumAllocations = count;
|
|
|
|
makeResident.PriorityList = &priority;
|
|
|
|
makeResident.Flags.CantTrimFurther = cantTrimFurther ? 1 : 0;
|
|
|
|
makeResident.Flags.MustSucceed = cantTrimFurther ? 1 : 0;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->makeResident(&makeResident);
|
2017-12-21 07:45:38 +08:00
|
|
|
if (status == STATUS_PENDING) {
|
2020-03-17 19:19:38 +08:00
|
|
|
perfLogResidencyMakeResident(residencyLogger.get(), true);
|
2019-06-06 00:41:42 +08:00
|
|
|
updatePagingFenceValue(makeResident.PagingFenceValue);
|
2017-12-21 07:45:38 +08:00
|
|
|
success = true;
|
|
|
|
} else if (status == STATUS_SUCCESS) {
|
2020-03-17 19:19:38 +08:00
|
|
|
perfLogResidencyMakeResident(residencyLogger.get(), false);
|
2017-12-21 07:45:38 +08:00
|
|
|
success = true;
|
|
|
|
} else {
|
|
|
|
DEBUG_BREAK_IF(true);
|
2020-03-17 19:19:38 +08:00
|
|
|
perfLogResidencyTrimRequired(residencyLogger.get(), makeResident.NumBytesToTrim);
|
2017-12-21 07:45:38 +08:00
|
|
|
if (numberOfBytesToTrim != nullptr)
|
|
|
|
*numberOfBytesToTrim = makeResident.NumBytesToTrim;
|
|
|
|
UNRECOVERABLE_IF(cantTrimFurther);
|
|
|
|
}
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyMakeResident(featureTable->ftrKmdDaf, getAdapter(), device, handles, count, getGdi()->escape);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
return success;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-01-29 01:12:39 +08:00
|
|
|
bool Wddm::mapGpuVirtualAddress(AllocationStorageData *allocationStorageData) {
|
2019-03-18 17:06:01 +08:00
|
|
|
return mapGpuVirtualAddress(allocationStorageData->osHandleStorage->gmm,
|
|
|
|
allocationStorageData->osHandleStorage->handle,
|
2019-12-03 17:21:33 +08:00
|
|
|
0u, MemoryConstants::maxSvmAddress, castToUint64(allocationStorageData->cpuPtr),
|
2019-03-18 17:06:01 +08:00
|
|
|
allocationStorageData->osHandleStorage->gpuPtr);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-03-18 17:06:01 +08:00
|
|
|
bool Wddm::mapGpuVirtualAddress(Gmm *gmm, D3DKMT_HANDLE handle, D3DGPU_VIRTUAL_ADDRESS minimumAddress, D3DGPU_VIRTUAL_ADDRESS maximumAddress, D3DGPU_VIRTUAL_ADDRESS preferredAddress, D3DGPU_VIRTUAL_ADDRESS &gpuPtr) {
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DDDI_MAPGPUVIRTUALADDRESS MapGPUVA = {0};
|
|
|
|
D3DDDIGPUVIRTUALADDRESS_PROTECTION_TYPE protectionType = {{{0}}};
|
|
|
|
protectionType.Write = TRUE;
|
|
|
|
|
2019-02-15 22:33:40 +08:00
|
|
|
uint64_t size = gmm->gmmResourceInfo->getSizeAllocation();
|
2018-07-12 21:42:46 +08:00
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
MapGPUVA.hPagingQueue = pagingQueue;
|
|
|
|
MapGPUVA.hAllocation = handle;
|
|
|
|
MapGPUVA.Protection = protectionType;
|
|
|
|
MapGPUVA.SizeInPages = size / MemoryConstants::pageSize;
|
|
|
|
MapGPUVA.OffsetInPages = 0;
|
|
|
|
|
2019-03-18 17:06:01 +08:00
|
|
|
MapGPUVA.BaseAddress = preferredAddress;
|
|
|
|
MapGPUVA.MinimumAddress = minimumAddress;
|
|
|
|
MapGPUVA.MaximumAddress = maximumAddress;
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
NTSTATUS status = getGdi()->mapGpuVirtualAddress(&MapGPUVA);
|
2018-06-21 17:36:47 +08:00
|
|
|
gpuPtr = GmmHelper::canonize(MapGPUVA.VirtualAddress);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
if (status == STATUS_PENDING) {
|
2019-06-06 00:41:42 +08:00
|
|
|
updatePagingFenceValue(MapGPUVA.PagingFenceValue);
|
2017-12-21 07:45:38 +08:00
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyMapGpuVA(featureTable->ftrKmdDaf, getAdapter(), device, handle, MapGPUVA.VirtualAddress, getGdi()->escape);
|
2018-10-03 01:10:29 +08:00
|
|
|
|
2019-11-07 01:14:30 +08:00
|
|
|
if (gmm->isRenderCompressed && rootDeviceEnvironment.pageTableManager.get()) {
|
|
|
|
return rootDeviceEnvironment.pageTableManager->updateAuxTable(gpuPtr, gmm, true);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2018-01-25 22:10:07 +08:00
|
|
|
|
2018-10-03 01:10:29 +08:00
|
|
|
return true;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:28:41 +08:00
|
|
|
D3DGPU_VIRTUAL_ADDRESS Wddm::reserveGpuVirtualAddress(D3DGPU_VIRTUAL_ADDRESS minimumAddress,
|
|
|
|
D3DGPU_VIRTUAL_ADDRESS maximumAddress,
|
|
|
|
D3DGPU_SIZE_T size) {
|
|
|
|
UNRECOVERABLE_IF(size % MemoryConstants::pageSize64k);
|
|
|
|
D3DDDI_RESERVEGPUVIRTUALADDRESS reserveGpuVirtualAddress = {};
|
|
|
|
reserveGpuVirtualAddress.MinimumAddress = minimumAddress;
|
|
|
|
reserveGpuVirtualAddress.MaximumAddress = maximumAddress;
|
|
|
|
reserveGpuVirtualAddress.hPagingQueue = this->pagingQueue;
|
|
|
|
reserveGpuVirtualAddress.Size = size;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
NTSTATUS status = getGdi()->reserveGpuVirtualAddress(&reserveGpuVirtualAddress);
|
2019-02-26 15:28:41 +08:00
|
|
|
UNRECOVERABLE_IF(status != STATUS_SUCCESS);
|
|
|
|
return reserveGpuVirtualAddress.VirtualAddress;
|
|
|
|
}
|
|
|
|
|
2019-01-24 23:25:26 +08:00
|
|
|
bool Wddm::freeGpuVirtualAddress(D3DGPU_VIRTUAL_ADDRESS &gpuPtr, uint64_t size) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DKMT_FREEGPUVIRTUALADDRESS FreeGPUVA = {0};
|
2020-02-05 17:49:54 +08:00
|
|
|
FreeGPUVA.hAdapter = getAdapter();
|
2018-06-21 17:36:47 +08:00
|
|
|
FreeGPUVA.BaseAddress = GmmHelper::decanonize(gpuPtr);
|
2017-12-21 07:45:38 +08:00
|
|
|
FreeGPUVA.Size = size;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->freeGpuVirtualAddress(&FreeGPUVA);
|
2017-12-21 07:45:38 +08:00
|
|
|
gpuPtr = static_cast<D3DGPU_VIRTUAL_ADDRESS>(0);
|
2018-01-31 18:22:13 +08:00
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyUnmapGpuVA(featureTable->ftrKmdDaf, getAdapter(), device, FreeGPUVA.BaseAddress, getGdi()->escape);
|
2018-01-31 18:22:13 +08:00
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-02-26 01:58:09 +08:00
|
|
|
NTSTATUS Wddm::createAllocation(const void *alignedCpuPtr, const Gmm *gmm, D3DKMT_HANDLE &outHandle, D3DKMT_HANDLE &outResourceHandle, D3DKMT_HANDLE *outSharedHandle) {
|
2018-01-08 23:31:29 +08:00
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DDDI_ALLOCATIONINFO AllocationInfo = {0};
|
|
|
|
D3DKMT_CREATEALLOCATION CreateAllocation = {0};
|
|
|
|
|
2019-03-05 22:00:45 +08:00
|
|
|
if (gmm == nullptr)
|
2017-12-21 07:45:38 +08:00
|
|
|
return false;
|
|
|
|
|
2019-03-05 22:00:45 +08:00
|
|
|
AllocationInfo.pSystemMem = alignedCpuPtr;
|
|
|
|
AllocationInfo.pPrivateDriverData = gmm->gmmResourceInfo->peekHandle();
|
2017-12-21 07:45:38 +08:00
|
|
|
AllocationInfo.PrivateDriverDataSize = static_cast<unsigned int>(sizeof(GMM_RESOURCE_INFO));
|
|
|
|
AllocationInfo.Flags.Primary = 0;
|
|
|
|
|
|
|
|
CreateAllocation.hGlobalShare = 0;
|
|
|
|
CreateAllocation.PrivateRuntimeDataSize = 0;
|
|
|
|
CreateAllocation.PrivateDriverDataSize = 0;
|
|
|
|
CreateAllocation.Flags.Reserved = 0;
|
|
|
|
CreateAllocation.NumAllocations = 1;
|
|
|
|
CreateAllocation.pPrivateRuntimeData = NULL;
|
|
|
|
CreateAllocation.pPrivateDriverData = NULL;
|
|
|
|
CreateAllocation.Flags.NonSecure = FALSE;
|
2020-02-26 01:58:09 +08:00
|
|
|
CreateAllocation.Flags.CreateShared = outSharedHandle ? TRUE : FALSE;
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateAllocation.Flags.RestrictSharedAccess = FALSE;
|
2020-02-26 01:58:09 +08:00
|
|
|
CreateAllocation.Flags.CreateResource = outSharedHandle || alignedCpuPtr ? TRUE : FALSE;
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateAllocation.pAllocationInfo = &AllocationInfo;
|
|
|
|
CreateAllocation.hDevice = device;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->createAllocation(&CreateAllocation);
|
2018-02-07 05:43:38 +08:00
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
return status;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2018-01-31 18:22:13 +08:00
|
|
|
|
2019-03-05 22:00:45 +08:00
|
|
|
outHandle = AllocationInfo.hAllocation;
|
2020-02-26 01:58:09 +08:00
|
|
|
outResourceHandle = CreateAllocation.hResource;
|
|
|
|
if (outSharedHandle) {
|
|
|
|
*outSharedHandle = CreateAllocation.hGlobalShare;
|
|
|
|
}
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyWriteTarget(featureTable->ftrKmdDaf, getAdapter(), device, outHandle, getGdi()->escape);
|
2018-02-07 05:43:38 +08:00
|
|
|
|
2018-01-08 23:31:29 +08:00
|
|
|
return status;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-03-05 22:00:45 +08:00
|
|
|
bool Wddm::createAllocation64k(const Gmm *gmm, D3DKMT_HANDLE &outHandle) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DDDI_ALLOCATIONINFO AllocationInfo = {0};
|
|
|
|
D3DKMT_CREATEALLOCATION CreateAllocation = {0};
|
|
|
|
|
|
|
|
AllocationInfo.pSystemMem = 0;
|
2019-03-05 22:00:45 +08:00
|
|
|
AllocationInfo.pPrivateDriverData = gmm->gmmResourceInfo->peekHandle();
|
2017-12-21 07:45:38 +08:00
|
|
|
AllocationInfo.PrivateDriverDataSize = static_cast<unsigned int>(sizeof(GMM_RESOURCE_INFO));
|
|
|
|
AllocationInfo.Flags.Primary = 0;
|
|
|
|
|
|
|
|
CreateAllocation.NumAllocations = 1;
|
|
|
|
CreateAllocation.pPrivateRuntimeData = NULL;
|
|
|
|
CreateAllocation.pPrivateDriverData = NULL;
|
|
|
|
CreateAllocation.Flags.CreateResource = TRUE;
|
|
|
|
CreateAllocation.pAllocationInfo = &AllocationInfo;
|
|
|
|
CreateAllocation.hDevice = device;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->createAllocation(&CreateAllocation);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-08-28 18:56:05 +08:00
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2019-03-05 22:00:45 +08:00
|
|
|
outHandle = AllocationInfo.hAllocation;
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyWriteTarget(featureTable->ftrKmdDaf, getAdapter(), device, outHandle, getGdi()->escape);
|
2019-03-05 16:25:18 +08:00
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-23 17:07:31 +08:00
|
|
|
NTSTATUS Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
2018-10-22 20:20:05 +08:00
|
|
|
D3DDDI_ALLOCATIONINFO AllocationInfo[maxFragmentsCount] = {{0}};
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DKMT_CREATEALLOCATION CreateAllocation = {0};
|
|
|
|
|
|
|
|
auto allocationCount = 0;
|
2018-10-22 20:20:05 +08:00
|
|
|
for (unsigned int i = 0; i < maxFragmentsCount; i++) {
|
2017-12-21 07:45:38 +08:00
|
|
|
if (!osHandles.fragmentStorageData[i].osHandleStorage) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (osHandles.fragmentStorageData[i].osHandleStorage->handle == (D3DKMT_HANDLE) nullptr && osHandles.fragmentStorageData[i].fragmentSize) {
|
|
|
|
AllocationInfo[allocationCount].pPrivateDriverData = osHandles.fragmentStorageData[i].osHandleStorage->gmm->gmmResourceInfo->peekHandle();
|
|
|
|
auto pSysMem = osHandles.fragmentStorageData[i].cpuPtr;
|
2020-03-19 21:49:05 +08:00
|
|
|
auto PSysMemFromGmm = osHandles.fragmentStorageData[i].osHandleStorage->gmm->gmmResourceInfo->getSystemMemPointer();
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(PSysMemFromGmm != pSysMem);
|
|
|
|
AllocationInfo[allocationCount].pSystemMem = osHandles.fragmentStorageData[i].cpuPtr;
|
|
|
|
AllocationInfo[allocationCount].PrivateDriverDataSize = static_cast<unsigned int>(sizeof(GMM_RESOURCE_INFO));
|
|
|
|
allocationCount++;
|
|
|
|
}
|
|
|
|
}
|
2018-03-23 17:07:31 +08:00
|
|
|
if (allocationCount == 0) {
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
CreateAllocation.hGlobalShare = 0;
|
|
|
|
CreateAllocation.PrivateRuntimeDataSize = 0;
|
|
|
|
CreateAllocation.PrivateDriverDataSize = 0;
|
|
|
|
CreateAllocation.Flags.Reserved = 0;
|
|
|
|
CreateAllocation.NumAllocations = allocationCount;
|
|
|
|
CreateAllocation.pPrivateRuntimeData = NULL;
|
|
|
|
CreateAllocation.pPrivateDriverData = NULL;
|
|
|
|
CreateAllocation.Flags.NonSecure = FALSE;
|
|
|
|
CreateAllocation.Flags.CreateShared = FALSE;
|
|
|
|
CreateAllocation.Flags.RestrictSharedAccess = FALSE;
|
|
|
|
CreateAllocation.Flags.CreateResource = FALSE;
|
|
|
|
CreateAllocation.pAllocationInfo = AllocationInfo;
|
|
|
|
CreateAllocation.hDevice = device;
|
|
|
|
|
2018-03-23 17:07:31 +08:00
|
|
|
while (status == STATUS_UNSUCCESSFUL) {
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->createAllocation(&CreateAllocation);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DBG_LOG(PrintDebugMessages, __FUNCTION__, "status: ", status);
|
2019-02-01 15:32:25 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_GRAPHICS_NO_VIDEO_MEMORY);
|
2017-12-21 07:45:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
auto allocationIndex = 0;
|
|
|
|
for (int i = 0; i < allocationCount; i++) {
|
|
|
|
while (osHandles.fragmentStorageData[allocationIndex].osHandleStorage->handle) {
|
|
|
|
allocationIndex++;
|
|
|
|
}
|
|
|
|
osHandles.fragmentStorageData[allocationIndex].osHandleStorage->handle = AllocationInfo[i].hAllocation;
|
2019-01-29 01:12:39 +08:00
|
|
|
bool success = mapGpuVirtualAddress(&osHandles.fragmentStorageData[allocationIndex]);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
if (!success) {
|
2019-06-18 19:53:14 +08:00
|
|
|
osHandles.fragmentStorageData[allocationIndex].freeTheFragment = true;
|
2018-01-31 18:22:13 +08:00
|
|
|
DBG_LOG(PrintDebugMessages, __FUNCTION__, "mapGpuVirtualAddress: ", success);
|
|
|
|
DEBUG_BREAK_IF(true);
|
2019-06-18 19:53:14 +08:00
|
|
|
return STATUS_GRAPHICS_NO_VIDEO_MEMORY;
|
2018-01-31 18:22:13 +08:00
|
|
|
}
|
|
|
|
|
2019-06-18 19:53:14 +08:00
|
|
|
allocationIndex++;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyWriteTarget(featureTable->ftrKmdDaf, getAdapter(), device, AllocationInfo[i].hAllocation, getGdi()->escape);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-03-23 17:07:31 +08:00
|
|
|
status = STATUS_SUCCESS;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2018-03-23 17:07:31 +08:00
|
|
|
return status;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-03-05 21:21:57 +08:00
|
|
|
bool Wddm::destroyAllocations(const D3DKMT_HANDLE *handles, uint32_t allocationCount, D3DKMT_HANDLE resourceHandle) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DKMT_DESTROYALLOCATION2 DestroyAllocation = {0};
|
|
|
|
DEBUG_BREAK_IF(!(allocationCount <= 1 || resourceHandle == 0));
|
|
|
|
|
|
|
|
DestroyAllocation.hDevice = device;
|
|
|
|
DestroyAllocation.hResource = resourceHandle;
|
|
|
|
DestroyAllocation.phAllocationList = handles;
|
|
|
|
DestroyAllocation.AllocationCount = allocationCount;
|
|
|
|
|
|
|
|
DestroyAllocation.Flags.AssumeNotInUse = 1;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->destroyAllocation2(&DestroyAllocation);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc) {
|
|
|
|
D3DKMT_QUERYRESOURCEINFO QueryResourceInfo = {0};
|
|
|
|
QueryResourceInfo.hDevice = device;
|
|
|
|
QueryResourceInfo.hGlobalShare = handle;
|
2020-02-05 17:49:54 +08:00
|
|
|
auto status = getGdi()->queryResourceInfo(&QueryResourceInfo);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
2017-12-22 00:28:17 +08:00
|
|
|
if (QueryResourceInfo.NumAllocations == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
std::unique_ptr<char[]> allocPrivateData(new char[QueryResourceInfo.TotalPrivateDriverDataSize]);
|
|
|
|
std::unique_ptr<char[]> resPrivateData(new char[QueryResourceInfo.ResourcePrivateDriverDataSize]);
|
|
|
|
std::unique_ptr<char[]> resPrivateRuntimeData(new char[QueryResourceInfo.PrivateRuntimeDataSize]);
|
|
|
|
std::unique_ptr<D3DDDI_OPENALLOCATIONINFO[]> allocationInfo(new D3DDDI_OPENALLOCATIONINFO[QueryResourceInfo.NumAllocations]);
|
|
|
|
|
|
|
|
D3DKMT_OPENRESOURCE OpenResource = {0};
|
|
|
|
|
|
|
|
OpenResource.hDevice = device;
|
|
|
|
OpenResource.hGlobalShare = handle;
|
|
|
|
OpenResource.NumAllocations = QueryResourceInfo.NumAllocations;
|
|
|
|
OpenResource.pOpenAllocationInfo = allocationInfo.get();
|
|
|
|
OpenResource.pTotalPrivateDriverDataBuffer = allocPrivateData.get();
|
|
|
|
OpenResource.TotalPrivateDriverDataBufferSize = QueryResourceInfo.TotalPrivateDriverDataSize;
|
|
|
|
OpenResource.pResourcePrivateDriverData = resPrivateData.get();
|
|
|
|
OpenResource.ResourcePrivateDriverDataSize = QueryResourceInfo.ResourcePrivateDriverDataSize;
|
|
|
|
OpenResource.pPrivateRuntimeData = resPrivateRuntimeData.get();
|
|
|
|
OpenResource.PrivateRuntimeDataSize = QueryResourceInfo.PrivateRuntimeDataSize;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->openResource(&OpenResource);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
2019-03-05 16:25:18 +08:00
|
|
|
alloc->setDefaultHandle(allocationInfo[0].hAllocation);
|
2017-12-21 07:45:38 +08:00
|
|
|
alloc->resourceHandle = OpenResource.hResource;
|
|
|
|
|
2018-06-29 17:48:19 +08:00
|
|
|
auto resourceInfo = const_cast<void *>(allocationInfo[0].pPrivateDriverData);
|
2020-02-25 01:04:30 +08:00
|
|
|
alloc->setDefaultGmm(new Gmm(rootDeviceEnvironment.getGmmClientContext(), static_cast<GMM_RESOURCE_INFO *>(resourceInfo)));
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2017-12-22 00:28:17 +08:00
|
|
|
return true;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::openNTHandle(HANDLE handle, WddmAllocation *alloc) {
|
|
|
|
D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE queryResourceInfoFromNtHandle = {};
|
|
|
|
queryResourceInfoFromNtHandle.hDevice = device;
|
|
|
|
queryResourceInfoFromNtHandle.hNtHandle = handle;
|
2020-02-05 17:49:54 +08:00
|
|
|
auto status = getGdi()->queryResourceInfoFromNtHandle(&queryResourceInfoFromNtHandle);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
|
|
|
std::unique_ptr<char[]> allocPrivateData(new char[queryResourceInfoFromNtHandle.TotalPrivateDriverDataSize]);
|
|
|
|
std::unique_ptr<char[]> resPrivateData(new char[queryResourceInfoFromNtHandle.ResourcePrivateDriverDataSize]);
|
|
|
|
std::unique_ptr<char[]> resPrivateRuntimeData(new char[queryResourceInfoFromNtHandle.PrivateRuntimeDataSize]);
|
|
|
|
std::unique_ptr<D3DDDI_OPENALLOCATIONINFO2[]> allocationInfo2(new D3DDDI_OPENALLOCATIONINFO2[queryResourceInfoFromNtHandle.NumAllocations]);
|
|
|
|
|
|
|
|
D3DKMT_OPENRESOURCEFROMNTHANDLE openResourceFromNtHandle = {};
|
|
|
|
|
|
|
|
openResourceFromNtHandle.hDevice = device;
|
|
|
|
openResourceFromNtHandle.hNtHandle = handle;
|
|
|
|
openResourceFromNtHandle.NumAllocations = queryResourceInfoFromNtHandle.NumAllocations;
|
|
|
|
openResourceFromNtHandle.pOpenAllocationInfo2 = allocationInfo2.get();
|
|
|
|
openResourceFromNtHandle.pTotalPrivateDriverDataBuffer = allocPrivateData.get();
|
|
|
|
openResourceFromNtHandle.TotalPrivateDriverDataBufferSize = queryResourceInfoFromNtHandle.TotalPrivateDriverDataSize;
|
|
|
|
openResourceFromNtHandle.pResourcePrivateDriverData = resPrivateData.get();
|
|
|
|
openResourceFromNtHandle.ResourcePrivateDriverDataSize = queryResourceInfoFromNtHandle.ResourcePrivateDriverDataSize;
|
|
|
|
openResourceFromNtHandle.pPrivateRuntimeData = resPrivateRuntimeData.get();
|
|
|
|
openResourceFromNtHandle.PrivateRuntimeDataSize = queryResourceInfoFromNtHandle.PrivateRuntimeDataSize;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->openResourceFromNtHandle(&openResourceFromNtHandle);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
2019-03-05 16:25:18 +08:00
|
|
|
alloc->setDefaultHandle(allocationInfo2[0].hAllocation);
|
2017-12-21 07:45:38 +08:00
|
|
|
alloc->resourceHandle = openResourceFromNtHandle.hResource;
|
|
|
|
|
2018-06-29 17:48:19 +08:00
|
|
|
auto resourceInfo = const_cast<void *>(allocationInfo2[0].pPrivateDriverData);
|
2020-02-25 01:04:30 +08:00
|
|
|
alloc->setDefaultGmm(new Gmm(rootDeviceEnvironment.getGmmClientContext(), static_cast<GMM_RESOURCE_INFO *>(resourceInfo)));
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2017-12-22 00:28:17 +08:00
|
|
|
return true;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2020-03-17 19:19:38 +08:00
|
|
|
void *Wddm::lockResource(const D3DKMT_HANDLE &handle, bool applyMakeResidentPriorToLock, size_t size) {
|
2019-01-16 22:09:33 +08:00
|
|
|
|
2019-03-06 15:39:06 +08:00
|
|
|
if (applyMakeResidentPriorToLock) {
|
2020-03-17 19:19:38 +08:00
|
|
|
temporaryResources->makeResidentResource(handle, size);
|
2019-01-16 22:09:33 +08:00
|
|
|
}
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_LOCK2 lock2 = {};
|
|
|
|
|
2019-03-06 15:39:06 +08:00
|
|
|
lock2.hAllocation = handle;
|
2017-12-21 07:45:38 +08:00
|
|
|
lock2.hDevice = this->device;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->lock2(&lock2);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
2019-03-06 15:39:06 +08:00
|
|
|
kmDafLock(handle);
|
2017-12-21 07:45:38 +08:00
|
|
|
return lock2.pData;
|
|
|
|
}
|
|
|
|
|
2019-03-06 15:39:06 +08:00
|
|
|
void Wddm::unlockResource(const D3DKMT_HANDLE &handle) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_UNLOCK2 unlock2 = {};
|
|
|
|
|
2019-03-06 15:39:06 +08:00
|
|
|
unlock2.hAllocation = handle;
|
2017-12-21 07:45:38 +08:00
|
|
|
unlock2.hDevice = this->device;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->unlock2(&unlock2);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
2018-01-31 18:22:13 +08:00
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyUnlock(featureTable->ftrKmdDaf, getAdapter(), device, &handle, 1, getGdi()->escape);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-03-06 15:39:06 +08:00
|
|
|
void Wddm::kmDafLock(D3DKMT_HANDLE handle) {
|
2020-02-05 17:49:54 +08:00
|
|
|
kmDafListener->notifyLock(featureTable->ftrKmdDaf, getAdapter(), device, handle, 0, getGdi()->escape);
|
2018-03-23 04:13:45 +08:00
|
|
|
}
|
|
|
|
|
2019-03-01 19:21:30 +08:00
|
|
|
bool Wddm::createContext(OsContextWin &osContext) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_CREATECONTEXTVIRTUAL CreateContext = {0};
|
|
|
|
CREATECONTEXT_PVTDATA PrivateData = {{0}};
|
|
|
|
|
|
|
|
PrivateData.IsProtectedProcess = FALSE;
|
|
|
|
PrivateData.IsDwm = FALSE;
|
|
|
|
PrivateData.ProcessID = GetCurrentProcessId();
|
|
|
|
PrivateData.GpuVAContext = TRUE;
|
|
|
|
PrivateData.pHwContextId = &hwContextId;
|
|
|
|
PrivateData.IsMediaUsage = false;
|
2018-02-16 16:07:49 +08:00
|
|
|
PrivateData.NoRingFlushes = DebugManager.flags.UseNoRingFlushesKmdMode.get();
|
2019-03-01 19:21:30 +08:00
|
|
|
applyAdditionalContextFlags(PrivateData, osContext);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
CreateContext.EngineAffinity = 0;
|
2018-05-15 20:07:37 +08:00
|
|
|
CreateContext.Flags.NullRendering = static_cast<UINT>(DebugManager.flags.EnableNullHardware.get());
|
2018-08-10 22:41:44 +08:00
|
|
|
CreateContext.Flags.HwQueueSupported = wddmInterface->hwQueuesSupported();
|
2018-02-22 21:19:08 +08:00
|
|
|
|
2019-03-01 19:21:30 +08:00
|
|
|
if (osContext.getPreemptionMode() >= PreemptionMode::MidBatch) {
|
2018-02-22 21:19:08 +08:00
|
|
|
CreateContext.Flags.DisableGpuTimeout = readEnablePreemptionRegKey();
|
|
|
|
}
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateContext.PrivateDriverDataSize = sizeof(PrivateData);
|
2019-03-20 17:56:22 +08:00
|
|
|
CreateContext.NodeOrdinal = WddmEngineMapper::engineNodeMap(osContext.getEngineType());
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateContext.pPrivateDriverData = &PrivateData;
|
2019-10-23 23:16:09 +08:00
|
|
|
CreateContext.ClientHint = D3DKMT_CLIENTHINT_OPENCL;
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateContext.hDevice = device;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->createContext(&CreateContext);
|
2019-03-01 19:21:30 +08:00
|
|
|
osContext.setWddmContextHandle(CreateContext.hContext);
|
2018-05-02 18:00:28 +08:00
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::destroyContext(D3DKMT_HANDLE context) {
|
|
|
|
D3DKMT_DESTROYCONTEXT DestroyContext = {0};
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
|
|
|
if (context != static_cast<D3DKMT_HANDLE>(0)) {
|
|
|
|
DestroyContext.hContext = context;
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->destroyContext(&DestroyContext);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2018-05-02 18:00:28 +08:00
|
|
|
return status == STATUS_SUCCESS;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-12-16 22:42:13 +08:00
|
|
|
bool Wddm::submit(uint64_t commandBuffer, size_t size, void *commandHeader, WddmSubmitArguments &submitArguments) {
|
2018-08-10 22:41:44 +08:00
|
|
|
bool status = false;
|
2019-12-16 22:42:13 +08:00
|
|
|
if (currentPagingFenceValue > *pagingFenceAddress && !waitOnGPU(submitArguments.contextHandle)) {
|
2018-08-10 22:41:44 +08:00
|
|
|
return false;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2019-12-16 22:42:13 +08:00
|
|
|
DBG_LOG(ResidencyDebugEnable, "Residency:", __FUNCTION__, "currentFenceValue =", submitArguments.monitorFence->currentFenceValue);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2019-12-16 22:42:13 +08:00
|
|
|
status = wddmInterface->submit(commandBuffer, size, commandHeader, submitArguments);
|
2018-08-10 22:41:44 +08:00
|
|
|
if (status) {
|
2019-12-16 22:42:13 +08:00
|
|
|
submitArguments.monitorFence->lastSubmittedFence = submitArguments.monitorFence->currentFenceValue;
|
|
|
|
submitArguments.monitorFence->currentFenceValue++;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
getDeviceState();
|
|
|
|
|
2018-08-10 22:41:44 +08:00
|
|
|
return status;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-03-27 16:06:08 +08:00
|
|
|
void Wddm::getDeviceState() {
|
2017-12-21 07:45:38 +08:00
|
|
|
#ifdef _DEBUG
|
|
|
|
D3DKMT_GETDEVICESTATE GetDevState;
|
|
|
|
memset(&GetDevState, 0, sizeof(GetDevState));
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
GetDevState.hDevice = device;
|
|
|
|
GetDevState.StateType = D3DKMT_DEVICESTATE_EXECUTION;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->getDeviceState(&GetDevState);
|
2018-03-27 16:06:08 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
2017-12-21 07:45:38 +08:00
|
|
|
if (status == STATUS_SUCCESS) {
|
2018-03-27 16:06:08 +08:00
|
|
|
DEBUG_BREAK_IF(GetDevState.ExecutionState != D3DKMT_DEVICEEXECUTION_ACTIVE);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-08-27 21:48:29 +08:00
|
|
|
void Wddm::handleCompletion(OsContextWin &osContext) {
|
2018-10-22 21:59:26 +08:00
|
|
|
auto &monitoredFence = osContext.getResidencyController().getMonitoredFence();
|
|
|
|
if (monitoredFence.cpuAddress) {
|
|
|
|
auto *currentTag = monitoredFence.cpuAddress;
|
|
|
|
while (*currentTag < monitoredFence.currentFenceValue - 1)
|
2017-12-21 07:45:38 +08:00
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int Wddm::readEnablePreemptionRegKey() {
|
|
|
|
return static_cast<unsigned int>(registryReader->getSetting("EnablePreemption", 1));
|
|
|
|
}
|
|
|
|
|
2018-08-21 23:36:08 +08:00
|
|
|
bool Wddm::waitOnGPU(D3DKMT_HANDLE context) {
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DKMT_WAITFORSYNCHRONIZATIONOBJECTFROMGPU WaitOnGPU = {0};
|
|
|
|
|
|
|
|
WaitOnGPU.hContext = context;
|
|
|
|
WaitOnGPU.ObjectCount = 1;
|
|
|
|
WaitOnGPU.ObjectHandleArray = &pagingQueueSyncObject;
|
|
|
|
uint64_t localPagingFenceValue = currentPagingFenceValue;
|
|
|
|
|
|
|
|
WaitOnGPU.MonitoredFenceValueArray = &localPagingFenceValue;
|
2020-02-05 17:49:54 +08:00
|
|
|
NTSTATUS status = getGdi()->waitForSynchronizationObjectFromGpu(&WaitOnGPU);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-10-26 18:22:47 +08:00
|
|
|
bool Wddm::waitFromCpu(uint64_t lastFenceValue, const MonitoredFence &monitoredFence) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
2018-10-26 18:22:47 +08:00
|
|
|
if (lastFenceValue > *monitoredFence.cpuAddress) {
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DKMT_WAITFORSYNCHRONIZATIONOBJECTFROMCPU waitFromCpu = {0};
|
|
|
|
waitFromCpu.ObjectCount = 1;
|
2018-10-26 18:22:47 +08:00
|
|
|
waitFromCpu.ObjectHandleArray = &monitoredFence.fenceHandle;
|
2017-12-21 07:45:38 +08:00
|
|
|
waitFromCpu.FenceValueArray = &lastFenceValue;
|
|
|
|
waitFromCpu.hDevice = device;
|
|
|
|
waitFromCpu.hAsyncEvent = NULL;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
status = getGdi()->waitForSynchronizationObjectFromCpu(&waitFromCpu);
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-01-30 00:48:36 +08:00
|
|
|
void Wddm::initGfxPartition(GfxPartition &outGfxPartition, uint32_t rootDeviceIndex, size_t numRootDevices) const {
|
2019-03-01 23:14:28 +08:00
|
|
|
if (gfxPartition.SVM.Limit != 0) {
|
|
|
|
outGfxPartition.heapInit(HeapIndex::HEAP_SVM, gfxPartition.SVM.Base, gfxPartition.SVM.Limit - gfxPartition.SVM.Base + 1);
|
2019-07-18 21:33:20 +08:00
|
|
|
} else if (is32bit) {
|
|
|
|
outGfxPartition.heapInit(HeapIndex::HEAP_SVM, 0x0ull, 4 * MemoryConstants::gigaByte);
|
2019-03-01 23:14:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
outGfxPartition.heapInit(HeapIndex::HEAP_STANDARD, gfxPartition.Standard.Base, gfxPartition.Standard.Limit - gfxPartition.Standard.Base + 1);
|
|
|
|
|
2020-01-30 00:48:36 +08:00
|
|
|
// Split HEAP_STANDARD64K among root devices
|
|
|
|
auto gfxStandard64KBSize = alignDown((gfxPartition.Standard64KB.Limit - gfxPartition.Standard64KB.Base + 1) / numRootDevices, GfxPartition::heapGranularity);
|
|
|
|
outGfxPartition.heapInit(HeapIndex::HEAP_STANDARD64KB, gfxPartition.Standard64KB.Base + rootDeviceIndex * gfxStandard64KBSize, gfxStandard64KBSize);
|
2019-03-01 23:14:28 +08:00
|
|
|
|
|
|
|
for (auto heap : GfxPartition::heap32Names) {
|
2019-04-15 21:20:51 +08:00
|
|
|
outGfxPartition.heapInit(heap, gfxPartition.Heap32[static_cast<uint32_t>(heap)].Base,
|
2019-03-01 23:14:28 +08:00
|
|
|
gfxPartition.Heap32[static_cast<uint32_t>(heap)].Limit - gfxPartition.Heap32[static_cast<uint32_t>(heap)].Base + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-03 04:43:37 +08:00
|
|
|
uint64_t Wddm::getSystemSharedMemory() const {
|
|
|
|
return systemSharedMemory;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-07-29 20:32:37 +08:00
|
|
|
uint64_t Wddm::getDedicatedVideoMemory() const {
|
|
|
|
return dedicatedVideoMemory;
|
|
|
|
}
|
|
|
|
|
2018-03-03 04:43:37 +08:00
|
|
|
uint64_t Wddm::getMaxApplicationAddress() const {
|
2017-12-21 07:45:38 +08:00
|
|
|
return maximumApplicationAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS Wddm::escape(D3DKMT_ESCAPE &escapeCommand) {
|
2020-02-05 17:49:54 +08:00
|
|
|
escapeCommand.hAdapter = getAdapter();
|
|
|
|
return getGdi()->escape(&escapeCommand);
|
2017-12-21 07:45:38 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
PFND3DKMT_ESCAPE Wddm::getEscapeHandle() const {
|
2020-02-05 17:49:54 +08:00
|
|
|
return getGdi()->escape;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-10-30 21:40:02 +08:00
|
|
|
VOID *Wddm::registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmResidencyController &residencyController) {
|
2018-09-18 09:23:04 +08:00
|
|
|
if (DebugManager.flags.DoNotRegisterTrimCallback.get()) {
|
2018-10-23 22:17:31 +08:00
|
|
|
return nullptr;
|
2018-09-18 09:23:04 +08:00
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DKMT_REGISTERTRIMNOTIFICATION registerTrimNotification;
|
|
|
|
registerTrimNotification.Callback = callback;
|
2020-02-05 17:49:54 +08:00
|
|
|
registerTrimNotification.AdapterLuid = hwDeviceId->getAdapterLuid();
|
2018-10-30 21:40:02 +08:00
|
|
|
registerTrimNotification.Context = &residencyController;
|
2020-02-05 17:49:54 +08:00
|
|
|
registerTrimNotification.hDevice = device;
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
NTSTATUS status = getGdi()->registerTrimNotification(®isterTrimNotification);
|
2017-12-21 07:45:38 +08:00
|
|
|
if (status == STATUS_SUCCESS) {
|
2018-10-23 22:17:31 +08:00
|
|
|
return registerTrimNotification.Handle;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2018-10-23 22:17:31 +08:00
|
|
|
return nullptr;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-10-23 22:17:31 +08:00
|
|
|
void Wddm::unregisterTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, VOID *trimCallbackHandle) {
|
|
|
|
DEBUG_BREAK_IF(callback == nullptr);
|
|
|
|
if (trimCallbackHandle == nullptr) {
|
2018-10-15 23:12:55 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
D3DKMT_UNREGISTERTRIMNOTIFICATION unregisterTrimNotification;
|
|
|
|
unregisterTrimNotification.Callback = callback;
|
2018-10-23 22:17:31 +08:00
|
|
|
unregisterTrimNotification.Handle = trimCallbackHandle;
|
2018-10-15 23:12:55 +08:00
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
NTSTATUS status = getGdi()->unregisterTrimNotification(&unregisterTrimNotification);
|
2018-10-15 23:12:55 +08:00
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-01-30 22:07:58 +08:00
|
|
|
void Wddm::releaseReservedAddress(void *reservedAddress) {
|
|
|
|
if (reservedAddress) {
|
2018-03-22 17:38:23 +08:00
|
|
|
auto status = virtualFree(reservedAddress, 0, MEM_RELEASE);
|
2018-01-30 22:07:58 +08:00
|
|
|
DEBUG_BREAK_IF(!status);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-30 22:07:58 +08:00
|
|
|
bool Wddm::reserveValidAddressRange(size_t size, void *&reservedMem) {
|
2018-03-22 17:38:23 +08:00
|
|
|
reservedMem = virtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
|
2018-01-30 22:07:58 +08:00
|
|
|
if (reservedMem == nullptr) {
|
|
|
|
return false;
|
|
|
|
} else if (minAddress > reinterpret_cast<uintptr_t>(reservedMem)) {
|
|
|
|
StackVec<void *, 100> invalidAddrVector;
|
|
|
|
invalidAddrVector.push_back(reservedMem);
|
|
|
|
do {
|
2018-03-22 17:38:23 +08:00
|
|
|
reservedMem = virtualAlloc(nullptr, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
|
2018-01-30 22:07:58 +08:00
|
|
|
if (minAddress > reinterpret_cast<uintptr_t>(reservedMem) && reservedMem != nullptr) {
|
|
|
|
invalidAddrVector.push_back(reservedMem);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (1);
|
|
|
|
for (auto &it : invalidAddrVector) {
|
2018-03-22 17:38:23 +08:00
|
|
|
auto status = virtualFree(it, 0, MEM_RELEASE);
|
2018-01-30 22:07:58 +08:00
|
|
|
DEBUG_BREAK_IF(!status);
|
|
|
|
}
|
|
|
|
if (reservedMem == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-22 17:38:23 +08:00
|
|
|
void *Wddm::virtualAlloc(void *inPtr, size_t size, unsigned long flags, unsigned long type) {
|
|
|
|
return virtualAllocFnc(inPtr, size, flags, type);
|
|
|
|
}
|
2018-05-18 16:18:16 +08:00
|
|
|
|
2018-03-22 17:38:23 +08:00
|
|
|
int Wddm::virtualFree(void *ptr, size_t size, unsigned long flags) {
|
|
|
|
return virtualFreeFnc(ptr, size, flags);
|
|
|
|
}
|
2018-08-23 17:29:39 +08:00
|
|
|
|
2019-12-23 21:28:33 +08:00
|
|
|
long __stdcall notifyAubCapture(void *csrHandle, uint64_t gfxAddress, size_t gfxSize, bool allocate) {
|
|
|
|
return notifyAubCaptureImpl(csrHandle, gfxAddress, gfxSize, allocate);
|
|
|
|
}
|
|
|
|
bool Wddm::configureDeviceAddressSpace() {
|
|
|
|
GMM_DEVICE_CALLBACKS_INT deviceCallbacks{};
|
2020-02-05 17:49:54 +08:00
|
|
|
deviceCallbacks.Adapter.KmtHandle = getAdapter();
|
2019-12-23 21:28:33 +08:00
|
|
|
deviceCallbacks.hCsr = nullptr;
|
|
|
|
deviceCallbacks.hDevice.KmtHandle = device;
|
|
|
|
deviceCallbacks.PagingQueue = pagingQueue;
|
|
|
|
deviceCallbacks.PagingFence = pagingQueueSyncObject;
|
|
|
|
|
2020-02-05 17:49:54 +08:00
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnAllocate = getGdi()->createAllocation;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnDeallocate = getGdi()->destroyAllocation;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnMapGPUVA = getGdi()->mapGpuVirtualAddress;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnMakeResident = getGdi()->makeResident;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnEvict = getGdi()->evict;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnReserveGPUVA = getGdi()->reserveGpuVirtualAddress;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnUpdateGPUVA = getGdi()->updateGpuVirtualAddress;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnWaitFromCpu = getGdi()->waitForSynchronizationObjectFromCpu;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnLock = getGdi()->lock2;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnUnLock = getGdi()->unlock2;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnEscape = getGdi()->escape;
|
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnFreeGPUVA = getGdi()->freeGpuVirtualAddress;
|
2019-12-23 21:28:33 +08:00
|
|
|
deviceCallbacks.DevCbPtrs.KmtCbPtrs.pfnNotifyAubCapture = notifyAubCapture;
|
|
|
|
|
|
|
|
GMM_DEVICE_INFO deviceInfo{};
|
|
|
|
deviceInfo.pGfxPartition = &gfxPartition;
|
|
|
|
deviceInfo.pDeviceCb = &deviceCallbacks;
|
|
|
|
if (!gmmMemory->setDeviceInfo(&deviceInfo)) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-08-23 17:29:39 +08:00
|
|
|
SYSTEM_INFO sysInfo;
|
|
|
|
Wddm::getSystemInfo(&sysInfo);
|
|
|
|
maximumApplicationAddress = reinterpret_cast<uintptr_t>(sysInfo.lpMaximumApplicationAddress);
|
2018-08-24 21:23:45 +08:00
|
|
|
auto productFamily = gfxPlatform->eProductFamily;
|
|
|
|
if (!hardwareInfoTable[productFamily]) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-10-22 00:30:24 +08:00
|
|
|
auto svmSize = hardwareInfoTable[productFamily]->capabilityTable.gpuAddressSpace >= MemoryConstants::max64BitAppAddress
|
2018-08-24 21:23:45 +08:00
|
|
|
? maximumApplicationAddress + 1u
|
|
|
|
: 0u;
|
2018-08-23 17:29:39 +08:00
|
|
|
|
2019-12-23 21:28:33 +08:00
|
|
|
bool obtainMinAddress = gfxPlatform->eRenderCoreFamily == IGFX_GEN12LP_CORE;
|
2020-02-05 17:49:54 +08:00
|
|
|
return gmmMemory->configureDevice(getAdapter(), device, getGdi()->escape, svmSize, featureTable->ftrL3IACoherency, minAddress, obtainMinAddress);
|
2018-08-23 17:29:39 +08:00
|
|
|
}
|
|
|
|
|
2019-07-12 22:50:14 +08:00
|
|
|
void Wddm::waitOnPagingFenceFromCpu() {
|
2020-03-17 19:19:38 +08:00
|
|
|
perfLogStartWaitTime(residencyLogger.get());
|
2019-01-16 22:09:33 +08:00
|
|
|
while (currentPagingFenceValue > *getPagingFenceAddress())
|
2020-03-17 19:19:38 +08:00
|
|
|
perfLogResidencyEnteredWait(residencyLogger.get());
|
|
|
|
|
|
|
|
perfLogResidencyWaitPagingeFenceLog(residencyLogger.get());
|
2019-01-16 22:09:33 +08:00
|
|
|
}
|
|
|
|
|
2019-10-15 21:05:47 +08:00
|
|
|
void Wddm::setGmmInputArg(void *args) {
|
|
|
|
reinterpret_cast<GMM_INIT_IN_ARGS *>(args)->stAdapterBDF = this->adapterBDF;
|
|
|
|
}
|
|
|
|
|
2019-06-06 00:41:42 +08:00
|
|
|
void Wddm::updatePagingFenceValue(uint64_t newPagingFenceValue) {
|
|
|
|
interlockedMax(currentPagingFenceValue, newPagingFenceValue);
|
|
|
|
}
|
|
|
|
|
2019-12-17 21:29:28 +08:00
|
|
|
WddmVersion Wddm::getWddmVersion() {
|
|
|
|
if (featureTable->ftrWddmHwQueues) {
|
|
|
|
return WddmVersion::WDDM_2_3;
|
|
|
|
} else {
|
|
|
|
return WddmVersion::WDDM_2_0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 19:19:38 +08:00
|
|
|
void Wddm::createPagingFenceLogger() {
|
|
|
|
if (DebugManager.flags.WddmResidencyLogger.get()) {
|
|
|
|
residencyLogger = std::make_unique<WddmResidencyLogger>(device, pagingFenceAddress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-26 18:59:46 +08:00
|
|
|
} // namespace NEO
|