2017-12-21 07:45:38 +08:00
|
|
|
/*
|
2018-01-08 11:07:46 +08:00
|
|
|
* Copyright (c) 2018, Intel Corporation
|
2017-12-21 07:45:38 +08:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "runtime/helpers/aligned_memory.h"
|
|
|
|
#include "runtime/helpers/options.h"
|
|
|
|
#include "runtime/os_interface/windows/gdi_interface.h"
|
2018-01-31 18:22:13 +08:00
|
|
|
#include "runtime/os_interface/windows/kmdaf_listener.h"
|
2017-12-21 07:45:38 +08:00
|
|
|
#include "runtime/gmm_helper/gmm_helper.h"
|
|
|
|
#include "runtime/gmm_helper/resource_info.h"
|
|
|
|
#include "runtime/gmm_helper/page_table_mngr.h"
|
|
|
|
#include "runtime/os_interface/windows/wddm.h"
|
|
|
|
#include "runtime/os_interface/windows/wddm_allocation.h"
|
|
|
|
#include "runtime/os_interface/windows/registry_reader.h"
|
|
|
|
#include "runtime/helpers/debug_helpers.h"
|
|
|
|
#include "runtime/helpers/hw_info.h"
|
|
|
|
#include "runtime/helpers/wddm_helper.h"
|
|
|
|
#include "runtime/command_stream/linear_stream.h"
|
2018-01-09 21:08:34 +08:00
|
|
|
#include "runtime/sku_info/operations/sku_info_receiver.h"
|
2018-01-30 22:07:58 +08:00
|
|
|
#include "runtime/utilities/stackvec.h"
|
2017-12-21 07:45:38 +08:00
|
|
|
#include <dxgi.h>
|
|
|
|
#include <ntstatus.h>
|
|
|
|
#include "CL/cl.h"
|
|
|
|
|
|
|
|
namespace OCLRT {
|
|
|
|
extern Wddm::CreateDXGIFactoryFcn getCreateDxgiFactory();
|
|
|
|
extern Wddm::GetSystemInfoFcn getGetSystemInfo();
|
|
|
|
|
|
|
|
class WddmMemoryManager;
|
|
|
|
|
|
|
|
Wddm::CreateDXGIFactoryFcn Wddm::createDxgiFactory = getCreateDxgiFactory();
|
|
|
|
Wddm::GetSystemInfoFcn Wddm::getSystemInfo = getGetSystemInfo();
|
|
|
|
|
|
|
|
Wddm::Wddm(Gdi *gdi) : initialized(false),
|
|
|
|
gdiAllocated(false),
|
|
|
|
gdi(gdi),
|
|
|
|
adapter(0),
|
|
|
|
context(0),
|
|
|
|
device(0),
|
|
|
|
pagingQueue(0),
|
|
|
|
pagingQueueSyncObject(0),
|
|
|
|
pagingFenceAddress(nullptr),
|
|
|
|
currentPagingFenceValue(0),
|
|
|
|
hwContextId(0),
|
|
|
|
trimCallbackHandle(nullptr) {
|
2018-03-03 04:43:37 +08:00
|
|
|
featureTable.reset(new FeatureTable());
|
|
|
|
waTable.reset(new WorkaroundTable());
|
|
|
|
gtSystemInfo.reset(new GT_SYSTEM_INFO);
|
|
|
|
gfxPlatform.reset(new PLATFORM);
|
|
|
|
memset(gtSystemInfo.get(), 0, sizeof(*gtSystemInfo));
|
|
|
|
memset(gfxPlatform.get(), 0, sizeof(*gfxPlatform));
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
registryReader.reset(new RegistryReader("System\\CurrentControlSet\\Control\\GraphicsDrivers\\Scheduler"));
|
|
|
|
adapterLuid.HighPart = 0;
|
|
|
|
adapterLuid.LowPart = 0;
|
|
|
|
maximumApplicationAddress = 0;
|
|
|
|
node = GPUNODE_3D;
|
2018-02-06 18:58:05 +08:00
|
|
|
preemptionMode = PreemptionMode::Disabled;
|
2017-12-21 07:45:38 +08:00
|
|
|
gmmMemory = std::unique_ptr<GmmMemory>(GmmMemory::create());
|
2018-01-22 23:43:26 +08:00
|
|
|
minAddress = 0;
|
2018-01-31 18:22:13 +08:00
|
|
|
kmDafListener = std::unique_ptr<KmDafListener>(new KmDafListener);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Wddm::Wddm() : Wddm(new Gdi()) {
|
|
|
|
gdiAllocated = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Wddm::~Wddm() {
|
|
|
|
resetPageTableManager(nullptr);
|
|
|
|
if (initialized)
|
|
|
|
Gmm::destroyContext();
|
|
|
|
destroyContext(context);
|
|
|
|
destroyPagingQueue();
|
|
|
|
destroyDevice();
|
|
|
|
closeAdapter();
|
|
|
|
if (gdiAllocated)
|
|
|
|
delete gdi;
|
|
|
|
}
|
|
|
|
|
2018-02-28 23:52:08 +08:00
|
|
|
bool Wddm::enumAdapters(unsigned int devNum, HardwareInfo &outHardwareInfo) {
|
2017-12-21 07:45:38 +08:00
|
|
|
bool success = false;
|
|
|
|
if (devNum > 0)
|
|
|
|
return false;
|
|
|
|
|
2018-02-28 23:52:08 +08:00
|
|
|
std::unique_ptr<Wddm> wddm(createWddm());
|
2017-12-21 07:45:38 +08:00
|
|
|
DEBUG_BREAK_IF(wddm == nullptr);
|
|
|
|
|
|
|
|
if (wddm->gdi->isInitialized()) {
|
|
|
|
do {
|
|
|
|
success = wddm->openAdapter();
|
|
|
|
if (!success)
|
|
|
|
break;
|
|
|
|
success = wddm->queryAdapterInfo();
|
|
|
|
if (!success)
|
|
|
|
break;
|
|
|
|
} while (!success);
|
|
|
|
}
|
2018-02-28 23:52:08 +08:00
|
|
|
if (success) {
|
2018-03-03 04:43:37 +08:00
|
|
|
auto productFamily = wddm->gfxPlatform->eProductFamily;
|
2018-02-28 23:52:08 +08:00
|
|
|
if (hardwareInfoTable[productFamily] == nullptr)
|
|
|
|
return false;
|
|
|
|
|
2018-03-03 04:43:37 +08:00
|
|
|
outHardwareInfo.pPlatform = new PLATFORM(*wddm->gfxPlatform);
|
|
|
|
outHardwareInfo.pSkuTable = new FeatureTable(*wddm->featureTable);
|
|
|
|
outHardwareInfo.pWaTable = new WorkaroundTable(*wddm->waTable);
|
|
|
|
outHardwareInfo.pSysInfo = new GT_SYSTEM_INFO(*wddm->gtSystemInfo);
|
2018-02-28 23:52:08 +08:00
|
|
|
|
|
|
|
outHardwareInfo.capabilityTable = hardwareInfoTable[productFamily]->capabilityTable;
|
2018-03-03 04:43:37 +08:00
|
|
|
outHardwareInfo.capabilityTable.maxRenderFrequency = wddm->maxRenderFrequency;
|
|
|
|
outHardwareInfo.capabilityTable.instrumentationEnabled &= wddm->instrumentationEnabled;
|
2018-02-28 23:52:08 +08:00
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::queryAdapterInfo() {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_QUERYADAPTERINFO QueryAdapterInfo = {0};
|
2018-03-03 04:43:37 +08:00
|
|
|
ADAPTER_INFO adapterInfo = {0};
|
2017-12-21 07:45:38 +08:00
|
|
|
QueryAdapterInfo.hAdapter = adapter;
|
|
|
|
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);
|
|
|
|
|
|
|
|
status = gdi->queryAdapterInfo(&QueryAdapterInfo);
|
|
|
|
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);
|
|
|
|
SkuInfoReceiver::receiveWaTableFromAdapterInfo(waTable.get(), &adapterInfo);
|
|
|
|
|
|
|
|
memcpy_s(&gfxPartition, sizeof(gfxPartition), &adapterInfo.GfxPartition, sizeof(GMM_GFX_PARTITIONING));
|
|
|
|
|
|
|
|
deviceRegistryPath = adapterInfo.DeviceRegistryPath;
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-03-03 04:43:37 +08:00
|
|
|
systemSharedMemory = adapterInfo.SystemSharedMemory;
|
|
|
|
maxRenderFrequency = adapterInfo.MaxRenderFreq;
|
|
|
|
instrumentationEnabled = adapterInfo.Caps.InstrumentationIsEnabled != 0;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::createPagingQueue() {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_CREATEPAGINGQUEUE CreatePagingQueue = {0};
|
|
|
|
CreatePagingQueue.hDevice = device;
|
|
|
|
CreatePagingQueue.Priority = D3DDDI_PAGINGQUEUE_PRIORITY_NORMAL;
|
|
|
|
|
|
|
|
status = gdi->createPagingQueue(&CreatePagingQueue);
|
|
|
|
|
|
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
pagingQueue = CreatePagingQueue.hPagingQueue;
|
|
|
|
pagingQueueSyncObject = CreatePagingQueue.hSyncObject;
|
|
|
|
pagingFenceAddress = reinterpret_cast<UINT64 *>(CreatePagingQueue.FenceValueCPUVirtualAddress);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::destroyPagingQueue() {
|
|
|
|
D3DDDI_DESTROYPAGINGQUEUE DestroyPagingQueue = {0};
|
|
|
|
if (pagingQueue) {
|
|
|
|
DestroyPagingQueue.hPagingQueue = pagingQueue;
|
|
|
|
|
|
|
|
NTSTATUS status = gdi->destroyPagingQueue(&DestroyPagingQueue);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
pagingQueue = 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::createDevice() {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_CREATEDEVICE CreateDevice = {{0}};
|
|
|
|
if (adapter) {
|
|
|
|
CreateDevice.hAdapter = adapter;
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
status = gdi->createDevice(&CreateDevice);
|
|
|
|
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;
|
|
|
|
|
|
|
|
status = gdi->destroyDevice(&DestroyDevice);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
device = 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::createMonitoredFence() {
|
|
|
|
NTSTATUS Status;
|
|
|
|
D3DKMT_CREATESYNCHRONIZATIONOBJECT2 CreateSynchronizationObject = {0};
|
|
|
|
DEBUG_BREAK_IF(!device);
|
|
|
|
CreateSynchronizationObject.hDevice = device;
|
|
|
|
CreateSynchronizationObject.Info.Type = D3DDDI_MONITORED_FENCE;
|
|
|
|
CreateSynchronizationObject.Info.MonitoredFence.InitialFenceValue = 0;
|
|
|
|
|
|
|
|
Status = gdi->createSynchronizationObject2(&CreateSynchronizationObject);
|
|
|
|
|
|
|
|
DEBUG_BREAK_IF(STATUS_SUCCESS != Status);
|
|
|
|
|
|
|
|
monitoredFence.currentFenceValue = 1;
|
|
|
|
monitoredFence.fenceHandle = CreateSynchronizationObject.hSyncObject;
|
|
|
|
monitoredFence.cpuAddress = reinterpret_cast<UINT64 *>(CreateSynchronizationObject.Info.MonitoredFence.FenceValueCPUVirtualAddress);
|
|
|
|
monitoredFence.lastSubmittedFence = 0;
|
|
|
|
|
|
|
|
monitoredFence.gpuAddress = CreateSynchronizationObject.Info.MonitoredFence.FenceValueGPUVirtualAddress;
|
|
|
|
|
|
|
|
return Status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::closeAdapter() {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_CLOSEADAPTER CloseAdapter = {0};
|
|
|
|
CloseAdapter.hAdapter = adapter;
|
|
|
|
status = gdi->closeAdapter(&CloseAdapter);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
adapter = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::openAdapter() {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_OPENADAPTERFROMLUID OpenAdapterData = {{0}};
|
|
|
|
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)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (pFactory->EnumAdapters1(iDevNum++, &pAdapter) != DXGI_ERROR_NOT_FOUND) {
|
|
|
|
hr = pAdapter->GetDesc1(&OpenAdapterDesc);
|
|
|
|
if (hr == S_OK) {
|
|
|
|
// 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) ||
|
|
|
|
(wcsstr(OpenAdapterDesc.Description, L"Citrix") != 0)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Release all the non-Intel adapters
|
|
|
|
pAdapter->Release();
|
|
|
|
pAdapter = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
OpenAdapterData.AdapterLuid = OpenAdapterDesc.AdapterLuid;
|
|
|
|
status = gdi->openAdapterFromLuid(&OpenAdapterData);
|
|
|
|
|
|
|
|
if (pAdapter != nullptr) {
|
|
|
|
// If an Intel adapter was found, release it here
|
|
|
|
pAdapter->Release();
|
|
|
|
pAdapter = nullptr;
|
|
|
|
}
|
|
|
|
if (pFactory != nullptr) {
|
|
|
|
pFactory->Release();
|
|
|
|
pFactory = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
adapter = OpenAdapterData.hAdapter;
|
|
|
|
adapterLuid = OpenAdapterDesc.AdapterLuid;
|
|
|
|
}
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::evict(D3DKMT_HANDLE *handleList, uint32_t numOfHandles, uint64_t &sizeToTrim) {
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DKMT_EVICT Evict = {0};
|
|
|
|
Evict.AllocationList = handleList;
|
|
|
|
Evict.hDevice = device;
|
|
|
|
Evict.NumAllocations = numOfHandles;
|
|
|
|
Evict.NumBytesToTrim = 0;
|
|
|
|
|
|
|
|
status = gdi->evict(&Evict);
|
|
|
|
|
|
|
|
sizeToTrim = Evict.NumBytesToTrim;
|
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
kmDafListener->notifyEvict(featureTable->ftrKmdDaf, adapter, device, handleList, numOfHandles, gdi->escape);
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::makeResident(D3DKMT_HANDLE *handles, uint32_t count, bool cantTrimFurther, uint64_t *numberOfBytesToTrim) {
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DDDI_MAKERESIDENT makeResident = {0};
|
|
|
|
UINT priority = 0;
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
makeResident.AllocationList = handles;
|
|
|
|
makeResident.hPagingQueue = pagingQueue;
|
|
|
|
makeResident.NumAllocations = count;
|
|
|
|
makeResident.PriorityList = &priority;
|
|
|
|
makeResident.Flags.CantTrimFurther = cantTrimFurther ? 1 : 0;
|
|
|
|
makeResident.Flags.MustSucceed = cantTrimFurther ? 1 : 0;
|
|
|
|
|
|
|
|
status = gdi->makeResident(&makeResident);
|
|
|
|
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
interlockedMax(currentPagingFenceValue, makeResident.PagingFenceValue);
|
|
|
|
success = true;
|
|
|
|
} else if (status == STATUS_SUCCESS) {
|
|
|
|
success = true;
|
|
|
|
} else {
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
if (numberOfBytesToTrim != nullptr)
|
|
|
|
*numberOfBytesToTrim = makeResident.NumBytesToTrim;
|
|
|
|
UNRECOVERABLE_IF(cantTrimFurther);
|
|
|
|
}
|
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
kmDafListener->notifyMakeResident(featureTable->ftrKmdDaf, adapter, device, handles, count, gdi->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
|
|
|
}
|
|
|
|
|
2018-02-27 18:08:22 +08:00
|
|
|
bool Wddm::mapGpuVirtualAddress(WddmAllocation *allocation, void *cpuPtr, uint64_t size, bool allocation32bit, bool use64kbPages, bool useHeap1) {
|
2018-01-30 22:07:58 +08:00
|
|
|
void *mapPtr = allocation->getReservedAddress() != nullptr ? allocation->getReservedAddress() : cpuPtr;
|
2018-02-27 18:08:22 +08:00
|
|
|
return mapGpuVirtualAddressImpl(allocation->gmm, allocation->handle, mapPtr, size, allocation->gpuPtr, allocation32bit, use64kbPages, useHeap1);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::mapGpuVirtualAddress(AllocationStorageData *allocationStorageData, bool allocation32bit, bool use64kbPages) {
|
|
|
|
return mapGpuVirtualAddressImpl(allocationStorageData->osHandleStorage->gmm,
|
|
|
|
allocationStorageData->osHandleStorage->handle,
|
|
|
|
const_cast<void *>(allocationStorageData->cpuPtr),
|
|
|
|
allocationStorageData->fragmentSize,
|
|
|
|
allocationStorageData->osHandleStorage->gpuPtr,
|
2018-02-27 18:08:22 +08:00
|
|
|
allocation32bit, use64kbPages, false);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-02-27 18:08:22 +08:00
|
|
|
bool Wddm::mapGpuVirtualAddressImpl(Gmm *gmm, D3DKMT_HANDLE handle, void *cpuPtr, uint64_t size, D3DGPU_VIRTUAL_ADDRESS &gpuPtr, bool allocation32bit, bool use64kbPages, bool useHeap1) {
|
2017-12-21 07:45:38 +08:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DDDI_MAPGPUVIRTUALADDRESS MapGPUVA = {0};
|
|
|
|
D3DDDIGPUVIRTUALADDRESS_PROTECTION_TYPE protectionType = {{{0}}};
|
|
|
|
protectionType.Write = TRUE;
|
|
|
|
|
|
|
|
MapGPUVA.hPagingQueue = pagingQueue;
|
|
|
|
MapGPUVA.hAllocation = handle;
|
|
|
|
MapGPUVA.Protection = protectionType;
|
|
|
|
MapGPUVA.SizeInPages = size / MemoryConstants::pageSize;
|
|
|
|
MapGPUVA.OffsetInPages = 0;
|
|
|
|
|
2018-02-27 18:08:22 +08:00
|
|
|
if (useHeap1) {
|
2018-03-03 04:43:37 +08:00
|
|
|
MapGPUVA.MinimumAddress = gfxPartition.Heap32[1].Base;
|
|
|
|
MapGPUVA.MaximumAddress = gfxPartition.Heap32[1].Limit;
|
2018-02-27 18:08:22 +08:00
|
|
|
MapGPUVA.BaseAddress = 0;
|
|
|
|
} else if (use64kbPages) {
|
2018-03-03 04:43:37 +08:00
|
|
|
MapGPUVA.MinimumAddress = gfxPartition.Standard64KB.Base;
|
|
|
|
MapGPUVA.MaximumAddress = gfxPartition.Standard64KB.Limit;
|
2017-12-21 07:45:38 +08:00
|
|
|
} else {
|
|
|
|
MapGPUVA.BaseAddress = reinterpret_cast<D3DGPU_VIRTUAL_ADDRESS>(cpuPtr);
|
|
|
|
MapGPUVA.MinimumAddress = static_cast<D3DGPU_VIRTUAL_ADDRESS>(0x0);
|
2018-01-30 22:07:58 +08:00
|
|
|
MapGPUVA.MaximumAddress = static_cast<D3DGPU_VIRTUAL_ADDRESS>((sizeof(size_t) == 8) ? 0x7fffffffffff : (D3DGPU_VIRTUAL_ADDRESS)0xffffffff);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
if (!cpuPtr) {
|
2018-03-03 04:43:37 +08:00
|
|
|
MapGPUVA.MinimumAddress = gfxPartition.Standard.Base;
|
|
|
|
MapGPUVA.MaximumAddress = gfxPartition.Standard.Limit;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
if (allocation32bit) {
|
2018-03-03 04:43:37 +08:00
|
|
|
MapGPUVA.MinimumAddress = gfxPartition.Heap32[0].Base;
|
|
|
|
MapGPUVA.MaximumAddress = gfxPartition.Heap32[0].Limit;
|
2017-12-21 07:45:38 +08:00
|
|
|
MapGPUVA.BaseAddress = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
status = gdi->mapGpuVirtualAddress(&MapGPUVA);
|
|
|
|
gpuPtr = Gmm::canonize(MapGPUVA.VirtualAddress);
|
|
|
|
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
interlockedMax(currentPagingFenceValue, MapGPUVA.PagingFenceValue);
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-25 22:10:07 +08:00
|
|
|
if (gmm->isRenderCompressed) {
|
|
|
|
return updateAuxTable(gpuPtr, gmm, true);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
2018-01-25 22:10:07 +08:00
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
kmDafListener->notifyMapGpuVA(featureTable->ftrKmdDaf, adapter, device, handle, MapGPUVA.VirtualAddress, gdi->escape);
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::freeGpuVirtualAddres(D3DGPU_VIRTUAL_ADDRESS &gpuPtr, uint64_t size) {
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DKMT_FREEGPUVIRTUALADDRESS FreeGPUVA = {0};
|
|
|
|
FreeGPUVA.hAdapter = adapter;
|
2018-01-31 18:22:13 +08:00
|
|
|
FreeGPUVA.BaseAddress = Gmm::decanonize(gpuPtr);
|
2017-12-21 07:45:38 +08:00
|
|
|
FreeGPUVA.Size = size;
|
|
|
|
|
|
|
|
status = gdi->freeGpuVirtualAddress(&FreeGPUVA);
|
|
|
|
gpuPtr = static_cast<D3DGPU_VIRTUAL_ADDRESS>(0);
|
2018-01-31 18:22:13 +08:00
|
|
|
|
|
|
|
kmDafListener->notifyUnmapGpuVA(featureTable->ftrKmdDaf, adapter, device, FreeGPUVA.BaseAddress, gdi->escape);
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-01-08 23:31:29 +08:00
|
|
|
NTSTATUS Wddm::createAllocation(WddmAllocation *alloc) {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DDDI_ALLOCATIONINFO AllocationInfo = {0};
|
|
|
|
D3DKMT_CREATEALLOCATION CreateAllocation = {0};
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
if (alloc == nullptr)
|
|
|
|
return false;
|
2018-02-02 00:16:36 +08:00
|
|
|
size = alloc->getAlignedSize();
|
2017-12-21 07:45:38 +08:00
|
|
|
if (size == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
AllocationInfo.pSystemMem = alloc->getAlignedCpuPtr();
|
|
|
|
AllocationInfo.pPrivateDriverData = alloc->gmm->gmmResourceInfo->peekHandle();
|
|
|
|
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;
|
|
|
|
CreateAllocation.Flags.CreateShared = FALSE;
|
|
|
|
CreateAllocation.Flags.RestrictSharedAccess = FALSE;
|
|
|
|
CreateAllocation.Flags.CreateResource = alloc->getAlignedCpuPtr() == 0 ? TRUE : FALSE;
|
|
|
|
CreateAllocation.pAllocationInfo = &AllocationInfo;
|
|
|
|
CreateAllocation.hDevice = device;
|
|
|
|
|
2018-02-07 05:43:38 +08:00
|
|
|
status = gdi->createAllocation(&CreateAllocation);
|
|
|
|
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
|
|
|
|
2018-02-07 05:43:38 +08:00
|
|
|
alloc->handle = AllocationInfo.hAllocation;
|
|
|
|
kmDafListener->notifyWriteTarget(featureTable->ftrKmdDaf, adapter, device, alloc->handle, gdi->escape);
|
|
|
|
|
2018-01-08 23:31:29 +08:00
|
|
|
return status;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::createAllocation64k(WddmAllocation *alloc) {
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DDDI_ALLOCATIONINFO AllocationInfo = {0};
|
|
|
|
D3DKMT_CREATEALLOCATION CreateAllocation = {0};
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
AllocationInfo.pSystemMem = 0;
|
|
|
|
AllocationInfo.pPrivateDriverData = alloc->gmm->gmmResourceInfo->peekHandle();
|
|
|
|
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;
|
|
|
|
|
|
|
|
while (!success) {
|
|
|
|
status = gdi->createAllocation(&CreateAllocation);
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
alloc->handle = AllocationInfo.hAllocation;
|
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
kmDafListener->notifyWriteTarget(featureTable->ftrKmdDaf, adapter, device, alloc->handle, gdi->escape);
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-23 17:07:31 +08:00
|
|
|
NTSTATUS Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DDDI_ALLOCATIONINFO AllocationInfo[max_fragments_count] = {{0}};
|
|
|
|
D3DKMT_CREATEALLOCATION CreateAllocation = {0};
|
|
|
|
|
|
|
|
auto allocationCount = 0;
|
|
|
|
for (unsigned int i = 0; i < max_fragments_count; i++) {
|
|
|
|
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;
|
|
|
|
auto PSysMemFromGmm = osHandles.fragmentStorageData[i].osHandleStorage->gmm->gmmResourceInfo->getSystemMemPointer(CL_TRUE);
|
|
|
|
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) {
|
2017-12-21 07:45:38 +08:00
|
|
|
status = gdi->createAllocation(&CreateAllocation);
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
DBG_LOG(PrintDebugMessages, __FUNCTION__, "status: ", status);
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
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;
|
2018-03-23 17:07:31 +08:00
|
|
|
bool success = mapGpuVirtualAddress(&osHandles.fragmentStorageData[allocationIndex], false, false);
|
2017-12-21 07:45:38 +08:00
|
|
|
allocationIndex++;
|
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
if (!success) {
|
|
|
|
DBG_LOG(PrintDebugMessages, __FUNCTION__, "mapGpuVirtualAddress: ", success);
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
kmDafListener->notifyWriteTarget(featureTable->ftrKmdDaf, adapter, device, AllocationInfo[i].hAllocation, gdi->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
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::destroyAllocations(D3DKMT_HANDLE *handles, uint32_t allocationCount, uint64_t lastFenceValue, D3DKMT_HANDLE resourceHandle) {
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
D3DKMT_DESTROYALLOCATION2 DestroyAllocation = {0};
|
|
|
|
DEBUG_BREAK_IF(!(allocationCount <= 1 || resourceHandle == 0));
|
|
|
|
waitFromCpu(lastFenceValue);
|
|
|
|
|
|
|
|
DestroyAllocation.hDevice = device;
|
|
|
|
DestroyAllocation.hResource = resourceHandle;
|
|
|
|
DestroyAllocation.phAllocationList = handles;
|
|
|
|
DestroyAllocation.AllocationCount = allocationCount;
|
|
|
|
|
|
|
|
DestroyAllocation.Flags.AssumeNotInUse = 1;
|
|
|
|
|
|
|
|
status = gdi->destroyAllocation2(&DestroyAllocation);
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc) {
|
|
|
|
D3DKMT_QUERYRESOURCEINFO QueryResourceInfo = {0};
|
|
|
|
QueryResourceInfo.hDevice = device;
|
|
|
|
QueryResourceInfo.hGlobalShare = handle;
|
|
|
|
auto status = gdi->queryResourceInfo(&QueryResourceInfo);
|
|
|
|
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;
|
|
|
|
|
|
|
|
status = gdi->openResource(&OpenResource);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
|
|
|
alloc->handle = allocationInfo[0].hAllocation;
|
|
|
|
alloc->resourceHandle = OpenResource.hResource;
|
|
|
|
|
|
|
|
alloc->gmm = Gmm::create((PGMM_RESOURCE_INFO)(allocationInfo[0].pPrivateDriverData));
|
|
|
|
|
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;
|
|
|
|
auto status = gdi->queryResourceInfoFromNtHandle(&queryResourceInfoFromNtHandle);
|
|
|
|
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;
|
|
|
|
|
|
|
|
status = gdi->openResourceFromNtHandle(&openResourceFromNtHandle);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
|
|
|
alloc->handle = allocationInfo2[0].hAllocation;
|
|
|
|
alloc->resourceHandle = openResourceFromNtHandle.hResource;
|
|
|
|
|
|
|
|
alloc->gmm = Gmm::create((PGMM_RESOURCE_INFO)(allocationInfo2[0].pPrivateDriverData));
|
|
|
|
|
2017-12-22 00:28:17 +08:00
|
|
|
return true;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void *Wddm::lockResource(WddmAllocation *wddmAllocation) {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_LOCK2 lock2 = {};
|
|
|
|
|
|
|
|
lock2.hAllocation = wddmAllocation->handle;
|
|
|
|
lock2.hDevice = this->device;
|
|
|
|
|
|
|
|
status = gdi->lock2(&lock2);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
|
2018-01-31 18:22:13 +08:00
|
|
|
kmDafListener->notifyLock(featureTable->ftrKmdDaf, adapter, device, wddmAllocation->handle, 0, gdi->escape);
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
return lock2.pData;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Wddm::unlockResource(WddmAllocation *wddmAllocation) {
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
D3DKMT_UNLOCK2 unlock2 = {};
|
|
|
|
|
|
|
|
unlock2.hAllocation = wddmAllocation->handle;
|
|
|
|
unlock2.hDevice = this->device;
|
|
|
|
|
|
|
|
status = gdi->unlock2(&unlock2);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
2018-01-31 18:22:13 +08:00
|
|
|
|
|
|
|
kmDafListener->notifyUnlock(featureTable->ftrKmdDaf, adapter, device, &wddmAllocation->handle, 1, gdi->escape);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-03-23 04:13:45 +08:00
|
|
|
void Wddm::kmDafLock(WddmAllocation *wddmAllocation) {
|
|
|
|
kmDafListener->notifyLock(featureTable->ftrKmdDaf, adapter, device, wddmAllocation->handle, 0, gdi->escape);
|
|
|
|
}
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DKMT_HANDLE Wddm::createContext() {
|
|
|
|
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();
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
CreateContext.EngineAffinity = 0;
|
|
|
|
CreateContext.Flags.NullRendering = (UINT)DebugManager.flags.EnableNullHardware.get();
|
2018-02-22 21:19:08 +08:00
|
|
|
|
|
|
|
if (preemptionMode >= PreemptionMode::MidBatch) {
|
|
|
|
CreateContext.Flags.DisableGpuTimeout = readEnablePreemptionRegKey();
|
|
|
|
}
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
CreateContext.PrivateDriverDataSize = sizeof(PrivateData);
|
|
|
|
CreateContext.NodeOrdinal = node;
|
|
|
|
CreateContext.pPrivateDriverData = &PrivateData;
|
|
|
|
CreateContext.ClientHint = D3DKMT_CLIENTHINT_OPENGL;
|
|
|
|
CreateContext.hDevice = device;
|
|
|
|
|
|
|
|
status = gdi->createContext(&CreateContext);
|
|
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
return CreateContext.hContext;
|
|
|
|
}
|
|
|
|
return static_cast<D3DKMT_HANDLE>(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::destroyContext(D3DKMT_HANDLE context) {
|
|
|
|
D3DKMT_DESTROYCONTEXT DestroyContext = {0};
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
|
|
|
if (context != static_cast<D3DKMT_HANDLE>(0)) {
|
|
|
|
DestroyContext.hContext = context;
|
|
|
|
status = gdi->destroyContext(&DestroyContext);
|
|
|
|
}
|
|
|
|
return status == STATUS_SUCCESS ? true : false;
|
|
|
|
}
|
|
|
|
|
2018-03-01 23:21:18 +08:00
|
|
|
bool Wddm::submit(uint64_t commandBuffer, size_t size, void *commandHeader) {
|
2017-12-21 07:45:38 +08:00
|
|
|
D3DKMT_SUBMITCOMMAND SubmitCommand = {0};
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
bool success = true;
|
|
|
|
|
2018-03-01 23:21:18 +08:00
|
|
|
SubmitCommand.Commands = commandBuffer;
|
2017-12-21 07:45:38 +08:00
|
|
|
SubmitCommand.CommandLength = static_cast<UINT>(size);
|
|
|
|
SubmitCommand.BroadcastContextCount = 1;
|
|
|
|
SubmitCommand.BroadcastContext[0] = context;
|
|
|
|
SubmitCommand.Flags.NullRendering = (UINT)DebugManager.flags.EnableNullHardware.get();
|
|
|
|
|
|
|
|
COMMAND_BUFFER_HEADER *pHeader = reinterpret_cast<COMMAND_BUFFER_HEADER *>(commandHeader);
|
|
|
|
|
|
|
|
pHeader->MonitorFenceVA = monitoredFence.gpuAddress;
|
|
|
|
pHeader->MonitorFenceValue = monitoredFence.currentFenceValue;
|
|
|
|
|
|
|
|
// Note: Private data should be the CPU VA Address
|
|
|
|
SubmitCommand.pPrivateDriverData = commandHeader;
|
|
|
|
SubmitCommand.PrivateDriverDataSize = sizeof(COMMAND_BUFFER_HEADER);
|
|
|
|
|
|
|
|
if (currentPagingFenceValue > *pagingFenceAddress) {
|
|
|
|
success = waitOnGPU();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
|
|
|
DBG_LOG(ResidencyDebugEnable, "Residency:", __FUNCTION__, "currentFenceValue =", monitoredFence.currentFenceValue);
|
|
|
|
|
|
|
|
status = gdi->submitCommand(&SubmitCommand);
|
|
|
|
if (STATUS_SUCCESS != status) {
|
|
|
|
success = false;
|
|
|
|
} else {
|
|
|
|
monitoredFence.lastSubmittedFence = monitoredFence.currentFenceValue;
|
|
|
|
monitoredFence.currentFenceValue++;
|
|
|
|
}
|
|
|
|
}
|
2017-12-20 20:24:19 +08:00
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
getDeviceState();
|
2017-12-20 20:24:19 +08:00
|
|
|
UNRECOVERABLE_IF(!success);
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
status = gdi->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
|
|
|
|
}
|
|
|
|
|
|
|
|
void Wddm::handleCompletion() {
|
|
|
|
if (monitoredFence.cpuAddress) {
|
|
|
|
auto *currentTag = monitoredFence.cpuAddress;
|
|
|
|
while (*currentTag < monitoredFence.currentFenceValue - 1)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int Wddm::readEnablePreemptionRegKey() {
|
|
|
|
return static_cast<unsigned int>(registryReader->getSetting("EnablePreemption", 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::waitOnGPU() {
|
|
|
|
D3DKMT_WAITFORSYNCHRONIZATIONOBJECTFROMGPU WaitOnGPU = {0};
|
|
|
|
|
|
|
|
WaitOnGPU.hContext = context;
|
|
|
|
WaitOnGPU.ObjectCount = 1;
|
|
|
|
WaitOnGPU.ObjectHandleArray = &pagingQueueSyncObject;
|
|
|
|
uint64_t localPagingFenceValue = currentPagingFenceValue;
|
|
|
|
|
|
|
|
WaitOnGPU.MonitoredFenceValueArray = &localPagingFenceValue;
|
|
|
|
NTSTATUS status = gdi->waitForSynchronizationObjectFromGpu(&WaitOnGPU);
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wddm::waitFromCpu(uint64_t lastFenceValue) {
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
if (lastFenceValue > *monitoredFence.cpuAddress) {
|
|
|
|
D3DKMT_WAITFORSYNCHRONIZATIONOBJECTFROMCPU waitFromCpu = {0};
|
|
|
|
waitFromCpu.ObjectCount = 1;
|
|
|
|
waitFromCpu.ObjectHandleArray = &monitoredFence.fenceHandle;
|
|
|
|
waitFromCpu.FenceValueArray = &lastFenceValue;
|
|
|
|
waitFromCpu.hDevice = device;
|
|
|
|
waitFromCpu.hAsyncEvent = NULL;
|
|
|
|
|
|
|
|
status = gdi->waitForSynchronizationObjectFromCpu(&waitFromCpu);
|
|
|
|
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status == STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-03-03 04:43:37 +08:00
|
|
|
uint64_t Wddm::getSystemSharedMemory() const {
|
|
|
|
return systemSharedMemory;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
escapeCommand.hAdapter = adapter;
|
|
|
|
return gdi->escape(&escapeCommand);
|
|
|
|
};
|
|
|
|
|
|
|
|
PFND3DKMT_ESCAPE Wddm::getEscapeHandle() const {
|
|
|
|
return gdi->escape;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t Wddm::getHeap32Base() {
|
2018-03-03 04:43:37 +08:00
|
|
|
return alignUp(gfxPartition.Heap32[0].Base, MemoryConstants::pageSize);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t Wddm::getHeap32Size() {
|
2018-03-03 04:43:37 +08:00
|
|
|
return alignDown(gfxPartition.Heap32[0].Limit, MemoryConstants::pageSize);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Wddm::registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmMemoryManager *memoryManager) {
|
|
|
|
D3DKMT_REGISTERTRIMNOTIFICATION registerTrimNotification;
|
|
|
|
registerTrimNotification.Callback = callback;
|
|
|
|
registerTrimNotification.AdapterLuid = this->adapterLuid;
|
|
|
|
registerTrimNotification.Context = memoryManager;
|
|
|
|
registerTrimNotification.hDevice = this->device;
|
|
|
|
|
|
|
|
NTSTATUS status = gdi->registerTrimNotification(®isterTrimNotification);
|
|
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
trimCallbackHandle = registerTrimNotification.Handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-30 22:07:58 +08:00
|
|
|
void Wddm::releaseReservedAddress(void *reservedAddress) {
|
|
|
|
if (reservedAddress) {
|
|
|
|
auto status = virtualFreeWrapper(reservedAddress, 0, MEM_RELEASE);
|
|
|
|
DEBUG_BREAK_IF(!status);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-25 22:10:07 +08:00
|
|
|
bool Wddm::updateAuxTable(D3DGPU_VIRTUAL_ADDRESS gpuVa, Gmm *gmm, bool map) {
|
|
|
|
if (pageTableManager.get()) {
|
|
|
|
GMM_DDI_UPDATEAUXTABLE ddiUpdateAuxTable = {};
|
|
|
|
ddiUpdateAuxTable.BaseGpuVA = gpuVa;
|
|
|
|
ddiUpdateAuxTable.BaseResInfo = gmm->gmmResourceInfo->peekHandle();
|
|
|
|
ddiUpdateAuxTable.DoNotWait = true;
|
|
|
|
ddiUpdateAuxTable.Map = map ? 1u : 0u;
|
|
|
|
return pageTableManager->updateAuxTable(&ddiUpdateAuxTable) == GMM_STATUS::GMM_SUCCESS;
|
|
|
|
}
|
|
|
|
return false;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Wddm::resetPageTableManager(GmmPageTableMngr *newPageTableManager) {
|
|
|
|
pageTableManager.reset(newPageTableManager);
|
|
|
|
}
|
|
|
|
|
2018-01-30 22:07:58 +08:00
|
|
|
bool Wddm::reserveValidAddressRange(size_t size, void *&reservedMem) {
|
|
|
|
reservedMem = virtualAllocWrapper(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
|
|
|
|
if (reservedMem == nullptr) {
|
|
|
|
return false;
|
|
|
|
} else if (minAddress > reinterpret_cast<uintptr_t>(reservedMem)) {
|
|
|
|
StackVec<void *, 100> invalidAddrVector;
|
|
|
|
invalidAddrVector.push_back(reservedMem);
|
|
|
|
do {
|
|
|
|
reservedMem = virtualAllocWrapper(nullptr, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
|
|
|
|
if (minAddress > reinterpret_cast<uintptr_t>(reservedMem) && reservedMem != nullptr) {
|
|
|
|
invalidAddrVector.push_back(reservedMem);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (1);
|
|
|
|
for (auto &it : invalidAddrVector) {
|
|
|
|
auto status = virtualFreeWrapper(it, 0, MEM_RELEASE);
|
|
|
|
DEBUG_BREAK_IF(!status);
|
|
|
|
}
|
|
|
|
if (reservedMem == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
} // namespace OCLRT
|