diff --git a/runtime/os_interface/windows/wddm.cpp b/runtime/os_interface/windows/wddm.cpp index ff6b24eb57..3d228f949b 100644 --- a/runtime/os_interface/windows/wddm.cpp +++ b/runtime/os_interface/windows/wddm.cpp @@ -426,7 +426,7 @@ NTSTATUS Wddm::createAllocation(WddmAllocation *alloc) { if (alloc == nullptr) return false; - size = alloc->getUnderlyingBufferSize(); + size = alloc->getAlignedSize(); if (size == 0) return false; @@ -450,9 +450,7 @@ NTSTATUS Wddm::createAllocation(WddmAllocation *alloc) { CreateAllocation.hDevice = device; while (status != STATUS_SUCCESS) { - status = gdi->createAllocation(&CreateAllocation); - if (status != STATUS_SUCCESS) { DEBUG_BREAK_IF(true); break; @@ -460,7 +458,6 @@ NTSTATUS Wddm::createAllocation(WddmAllocation *alloc) { alloc->handle = AllocationInfo.hAllocation; status = mapGpuVirtualAddress(alloc, alloc->getAlignedCpuPtr(), size, alloc->is32BitAllocation, false) == true ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; - if (status != STATUS_SUCCESS) { DEBUG_BREAK_IF(true); break; diff --git a/runtime/os_interface/windows/wddm_memory_manager.cpp b/runtime/os_interface/windows/wddm_memory_manager.cpp index 679cf7c360..678c9ce460 100644 --- a/runtime/os_interface/windows/wddm_memory_manager.cpp +++ b/runtime/os_interface/windows/wddm_memory_manager.cpp @@ -727,7 +727,7 @@ bool WddmMemoryManager::trimResidencyToBudget(uint64_t bytes) { if (wddmAllocation->fragmentsStorage.fragmentCount == 0) { wddm->evict(&wddmAllocation->handle, 1, sizeToTrim); - sizeEvicted = wddmAllocation->getUnderlyingBufferSize(); + sizeEvicted = wddmAllocation->getAlignedSize(); } else { for (uint32_t allocationId = 0; allocationId < wddmAllocation->fragmentsStorage.fragmentCount; allocationId++) { if (wddmAllocation->fragmentsStorage.fragmentStorageData[allocationId].residency->lastFence <= wddm->getMonitoredFence().lastSubmittedFence) { diff --git a/unit_tests/mock_gdi/gdi32_mock.def b/unit_tests/mock_gdi/gdi32_mock.def index 375b0aca00..f6645a1c25 100644 --- a/unit_tests/mock_gdi/gdi32_mock.def +++ b/unit_tests/mock_gdi/gdi32_mock.def @@ -1,4 +1,4 @@ -; Copyright (c) 2017, Intel Corporation +; Copyright (c) 2017 - 2018, Intel Corporation ; ; Permission is hereby granted, free of charge, to any person obtaining a ; copy of this software and associated documentation files (the "Software"), @@ -71,3 +71,4 @@ GetMockCreateDeviceParams SetMockCreateDeviceParams getMockAllocation getAdapterInfoAddress +getLastCallMapGpuVaArg diff --git a/unit_tests/mock_gdi/mock_gdi.cpp b/unit_tests/mock_gdi/mock_gdi.cpp index a4c66c22d6..4dca68a721 100644 --- a/unit_tests/mock_gdi/mock_gdi.cpp +++ b/unit_tests/mock_gdi/mock_gdi.cpp @@ -31,6 +31,7 @@ #include "runtime/os_interface/windows/os_time.h" ADAPTER_INFO gAdapterInfo = {0}; +D3DDDI_MAPGPUVIRTUALADDRESS gLastCallMapGpuVaArg = {0}; #ifdef __cplusplus // If used by C++ code, extern "C" { // we need to export the C interface @@ -222,7 +223,14 @@ NTSTATUS __stdcall D3DKMTDestroyAllocation2(IN CONST D3DKMT_DESTROYALLOCATION2 * NTSTATUS __stdcall D3DKMTMapGpuVirtualAddress(IN OUT D3DDDI_MAPGPUVIRTUALADDRESS *mapGpuVA) { uint64_t maxSvmAddress = sizeof(size_t) == 8 ? 0x7fffffffffff : 0xffffffff; - if (mapGpuVA == nullptr || mapGpuVA->hPagingQueue != PAGINGQUEUE_HANDLE) { + if (mapGpuVA == nullptr) { + memset(&gLastCallMapGpuVaArg, 0, sizeof(gLastCallMapGpuVaArg)); + return STATUS_INVALID_PARAMETER; + } + + memcpy(&gLastCallMapGpuVaArg, mapGpuVA, sizeof(gLastCallMapGpuVaArg)); + + if (mapGpuVA->hPagingQueue != PAGINGQUEUE_HANDLE) { return STATUS_INVALID_PARAMETER; } if (mapGpuVA->hAllocation != ALLOCATION_HANDLE && mapGpuVA->hAllocation != NT_ALLOCATION_HANDLE) { @@ -409,3 +417,7 @@ D3DKMT_CREATEALLOCATION *getMockAllocation() { ADAPTER_INFO *getAdapterInfoAddress() { return &gAdapterInfo; } + +D3DDDI_MAPGPUVIRTUALADDRESS *getLastCallMapGpuVaArg() { + return &gLastCallMapGpuVaArg; +} diff --git a/unit_tests/mock_gdi/mock_gdi.h b/unit_tests/mock_gdi/mock_gdi.h index 3a354040fc..b8f6145229 100644 --- a/unit_tests/mock_gdi/mock_gdi.h +++ b/unit_tests/mock_gdi/mock_gdi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -80,3 +80,4 @@ D3DKMT_CREATEDEVICE GetMockCreateDeviceParams(); void SetMockCreateDeviceParams(D3DKMT_CREATEDEVICE params); D3DKMT_CREATEALLOCATION *getMockAllocation(); ADAPTER_INFO *getAdapterInfoAddress(); +D3DDDI_MAPGPUVIRTUALADDRESS *getLastCallMapGpuVaArg(); diff --git a/unit_tests/os_interface/windows/wddm_fixture.h b/unit_tests/os_interface/windows/wddm_fixture.h index 2a2bb5728e..41ff1941d6 100644 --- a/unit_tests/os_interface/windows/wddm_fixture.h +++ b/unit_tests/os_interface/windows/wddm_fixture.h @@ -376,6 +376,7 @@ class WddmFixture { decltype(&SetMockCreateDeviceParams) setMockCreateDeviceParamsFcn; decltype(&getMockAllocation) getMockAllocationFcn; decltype(&getAdapterInfoAddress) getAdapterInfoAddressFcn; + decltype(&getLastCallMapGpuVaArg) getLastCallMapGpuVaArgFcn; public: virtual void SetUp() { @@ -394,6 +395,7 @@ class WddmFixture { reinterpret_cast(mockGdiDll->getProcAddress("SetMockCreateDeviceParams")); getMockAllocationFcn = reinterpret_cast(mockGdiDll->getProcAddress("getMockAllocation")); getAdapterInfoAddressFcn = reinterpret_cast(mockGdiDll->getProcAddress("getAdapterInfoAddress")); + getLastCallMapGpuVaArgFcn = reinterpret_cast(mockGdiDll->getProcAddress("getLastCallMapGpuVaArg")); wddm = Wddm::createWddm(); mockWddm = static_cast(wddm); wddm->registryReader.reset(new RegistryReaderMock()); diff --git a/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp b/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp index a7cf0e47e7..cddc96f30e 100644 --- a/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp +++ b/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp @@ -1239,6 +1239,54 @@ HWTEST_F(WddmMemoryManagerResidencyTest, checkTrimCandidateListCompaction) { EXPECT_FALSE(comapctionRequired); } +HWTEST_F(WddmMemoryManagerResidencyTest, givenThreeAllocationsAlignedSizeBiggerThanAllocSizeWhenBudgetEqualTwoAlignedAllocationThenEvictOnlyTwo) { + SetUpMm(); + WddmMock *mockWddm = static_cast(wddm); + gdi.setNonZeroNumBytesToTrimInEvict(); + size_t underlyingSize = 0xF00; + size_t alignedSize = 0x1000; + size_t budget = 2 * alignedSize; + + //trim budget should consider aligned size, not underlying, so if function considers underlying, it should evict three, not two + EXPECT_GT((3 * underlyingSize), budget); + EXPECT_LT((2 * underlyingSize), budget); + void *ptr1 = reinterpret_cast(mockWddm->virtualAllocAddress + 0x1000); + void *ptr2 = reinterpret_cast(mockWddm->virtualAllocAddress + 0x3000); + void *ptr3 = reinterpret_cast(mockWddm->virtualAllocAddress + 0x5000); + + WddmAllocation allocation1(ptr1, underlyingSize, ptr1, alignedSize, nullptr); + WddmAllocation allocation2(ptr2, underlyingSize, ptr2, alignedSize, nullptr); + WddmAllocation allocation3(ptr3, underlyingSize, ptr3, alignedSize, nullptr); + + allocation1.getResidencyData().resident = true; + allocation1.getResidencyData().lastFence = 0; + + allocation2.getResidencyData().lastFence = 1; + allocation2.getResidencyData().resident = true; + + allocation3.getResidencyData().lastFence = 1; + allocation3.getResidencyData().resident = true; + + *wddm->getMonitoredFence().cpuAddress = 1; + wddm->getMonitoredFence().lastSubmittedFence = 1; + wddm->getMonitoredFence().currentFenceValue = 1; + + mockWddm->makeNonResidentResult.called = 0; + + mm->trimCandidateList.resize(0); + + mm->addToTrimCandidateList(&allocation1); + mm->addToTrimCandidateList(&allocation2); + mm->addToTrimCandidateList(&allocation3); + + bool status = mm->trimResidencyToBudget(budget); + EXPECT_TRUE(status); + + EXPECT_FALSE(allocation1.getResidencyData().resident); + EXPECT_FALSE(allocation2.getResidencyData().resident); + EXPECT_TRUE(allocation3.getResidencyData().resident); +} + HWTEST_F(BufferWithWddmMemory, ValidHostPtr) { SetUpMm(); flags = CL_MEM_USE_HOST_PTR; diff --git a/unit_tests/os_interface/windows/wddm_tests.cpp b/unit_tests/os_interface/windows/wddm_tests.cpp index d21997eaab..106745aff0 100644 --- a/unit_tests/os_interface/windows/wddm_tests.cpp +++ b/unit_tests/os_interface/windows/wddm_tests.cpp @@ -130,6 +130,36 @@ HWTEST_F(WddmTest, allocation) { mm.freeSystemMemory(allocation.getUnderlyingBuffer()); } +HWTEST_F(WddmTest, givenAllocationSmallerUnderlyingThanAlignedSizeWhenCreatedThenWddmUseAligned) { + wddm->init(); + ASSERT_TRUE(wddm->isInitialized()); + + void *ptr = reinterpret_cast(mockWddm->virtualAllocAddress + 0x1000); + size_t underlyingSize = 0x2100; + size_t alignedSize = 0x3000; + + size_t underlyingPages = underlyingSize / MemoryConstants::pageSize; + size_t alignedPages = alignedSize / MemoryConstants::pageSize; + + WddmAllocation allocation(ptr, 0x2100, ptr, 0x3000, nullptr); + Gmm *gmm = getGmm(allocation.getAlignedCpuPtr(), allocation.getAlignedSize()); + ASSERT_NE(nullptr, gmm); + + allocation.gmm = gmm; + auto status = wddm->createAllocation(&allocation); + + EXPECT_EQ(STATUS_SUCCESS, status); + EXPECT_NE(0, allocation.handle); + + EXPECT_EQ(alignedPages, getLastCallMapGpuVaArgFcn()->SizeInPages); + EXPECT_NE(underlyingPages, getLastCallMapGpuVaArgFcn()->SizeInPages); + + auto ret = mockWddm->destroyAllocation(&allocation); + EXPECT_TRUE(ret); + + releaseGmm(gmm); +} + HWTEST_F(WddmTest, createAllocation32bit) { wddm->init(); ASSERT_TRUE(wddm->isInitialized());