fix: bindless image from usm pooled ptr

Add handling for creating bindless image from usm pooled ptr.
Make relevant ULTs test USM device pool enabled/disabled.

Related-To: NEO-6893

Signed-off-by: Dominik Dabek <dominik.dabek@intel.com>
This commit is contained in:
Dominik Dabek
2025-05-28 14:25:06 +00:00
committed by Compute-Runtime-Automation
parent ce1bcb536c
commit cdb088b477
2 changed files with 59 additions and 11 deletions

View File

@@ -18,6 +18,7 @@
#include "shared/source/memory_manager/allocation_properties.h"
#include "shared/source/memory_manager/memory_manager.h"
#include "shared/source/memory_manager/unified_memory_manager.h"
#include "shared/source/memory_manager/unified_memory_pooling.h"
#include "shared/source/release_helper/release_helper.h"
#include "level_zero/core/source/device/device.h"
@@ -105,6 +106,8 @@ ze_result_t ImageCoreFamily<gfxCoreFamily>::initialize(Device *device, const ze_
this->samplerDesc.pNext = nullptr;
}
NEO::UsmMemAllocPool *usmPool = nullptr;
if (!isImageView()) {
if (lookupTable.isSharedHandle) {
if (!lookupTable.sharedHandleType.isSupportedHandle) {
@@ -139,6 +142,15 @@ ze_result_t ImageCoreFamily<gfxCoreFamily>::initialize(Device *device, const ze_
if (usmAllocation == nullptr) {
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
if (this->device->getNEODevice()->getUsmMemAllocPool() &&
this->device->getNEODevice()->getUsmMemAllocPool()->isInPool(lookupTable.imageProperties.pitchedPtr)) {
usmPool = this->device->getNEODevice()->getUsmMemAllocPool();
if (nullptr == usmPool->getPooledAllocationBasePtr(lookupTable.imageProperties.pitchedPtr)) {
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
}
allocation = usmAllocation->gpuAllocations.getGraphicsAllocation(device->getRootDeviceIndex());
}
}
@@ -157,10 +169,14 @@ ze_result_t ImageCoreFamily<gfxCoreFamily>::initialize(Device *device, const ze_
imgInfo.rowPitch = imgInfo.imgDesc.imageWidth * imgInfo.surfaceFormat->imageElementSizeInBytes;
}
imgInfo.slicePitch = imgInfo.rowPitch * imgInfo.imgDesc.imageHeight;
imgInfo.size = allocation->getUnderlyingBufferSize();
imgInfo.qPitch = 0;
UNRECOVERABLE_IF(imgInfo.offset != 0);
if (!isImageView()) {
imgInfo.size = allocation->getUnderlyingBufferSize();
if (usmPool) {
imgInfo.size = usmPool->getPooledAllocationSize(lookupTable.imageProperties.pitchedPtr);
imgInfo.offset = usmPool->getOffsetInPool(lookupTable.imageProperties.pitchedPtr);
}
}
}
if (this->bindlessImage) {

View File

@@ -19,6 +19,7 @@
#include "shared/test/common/mocks/mock_gmm_client_context.h"
#include "shared/test/common/mocks/mock_memory_manager.h"
#include "shared/test/common/mocks/mock_sip.h"
#include "shared/test/common/mocks/mock_usm_memory_pool.h"
#include "shared/test/common/test_macros/hw_test.h"
#include "level_zero/core/source/gfx_core_helpers/l0_gfx_core_helper.h"
@@ -36,6 +37,19 @@ namespace ult {
using ImageCreate = Test<DeviceFixture>;
using ImageView = Test<DeviceFixture>;
struct ImageUsmPoolTest : ::testing::TestWithParam<int>, public DeviceFixture {
void SetUp() override {
NEO::debugManager.flags.EnableDeviceUsmAllocationPool.set(GetParam());
DeviceFixture::setUp();
}
void TearDown() override {
DeviceFixture::tearDown();
}
DebugManagerStateRestore restorer;
};
using ImageCreateUsmPool = ImageUsmPoolTest;
HWTEST_F(ImageCreate, givenValidImageDescriptionWhenImageCreateThenImageIsCreatedCorrectly) {
ze_image_desc_t zeDesc = {};
zeDesc.stype = ZE_STRUCTURE_TYPE_IMAGE_DESC;
@@ -1895,7 +1909,7 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenBindlessSlotAllocationFailsThenImag
ASSERT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, ret);
}
HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageCreatedWithInvalidPitchedPtrThenErrorIsReturned, ImageSupport) {
HWTEST2_P(ImageCreateUsmPool, GivenBindlessImageWhenImageCreatedWithInvalidPitchedPtrThenErrorIsReturned, ImageSupport) {
const size_t width = 32;
const size_t height = 32;
const size_t depth = 1;
@@ -1925,12 +1939,20 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageCreatedWithInvalidPitchedPtrTh
depth,
0,
0};
auto imageHW = std::make_unique<WhiteBox<::L0::ImageCoreFamily<FamilyType::gfxCoreFamily>>>();
auto ret = imageHW->initialize(device, &srcImgDesc);
ASSERT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, ret);
{
auto imageHW = std::make_unique<WhiteBox<::L0::ImageCoreFamily<FamilyType::gfxCoreFamily>>>();
auto ret = imageHW->initialize(device, &srcImgDesc);
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, ret);
}
if (auto usmPool = neoDevice->getUsmMemAllocPool()) {
pitchedDesc.ptr = reinterpret_cast<MockUsmMemAllocPool *>(usmPool)->pool; // not allocated ptr within USM pool
auto imageHW = std::make_unique<WhiteBox<::L0::ImageCoreFamily<FamilyType::gfxCoreFamily>>>();
auto ret = imageHW->initialize(device, &srcImgDesc);
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, ret);
}
}
HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageCreatedWithDeviceUMSPitchedPtrThenImageIsCreated, ImageSupport) {
HWTEST2_P(ImageCreateUsmPool, GivenBindlessImageWhenImageCreatedWithDeviceUSMPitchedPtrThenImageIsCreated, ImageSupport) {
const size_t width = 32;
const size_t height = 32;
const size_t depth = 1;
@@ -1949,6 +1971,10 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageCreatedWithDeviceUMSPitchedPtr
&ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, ret);
auto allocData = device->getDriverHandle()->getSvmAllocsManager()->getSVMAlloc(ptr);
const auto gpuAddress = allocData->gpuAllocations.getDefaultGraphicsAllocation()->getGpuAddress();
const auto offset = ptrDiff(castToUint64(ptr), gpuAddress);
ze_image_pitched_exp_desc_t pitchedDesc = {};
pitchedDesc.stype = ZE_STRUCTURE_TYPE_PITCHED_IMAGE_EXP_DESC;
pitchedDesc.ptr = ptr; // USM device pointer
@@ -1976,6 +2002,7 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageCreatedWithDeviceUMSPitchedPtr
EXPECT_TRUE(imageHW->bindlessImage);
EXPECT_TRUE(imageHW->imageFromBuffer);
EXPECT_EQ(offset, imageHW->imgInfo.offset);
size_t rowPitch = 0;
imageHW->getPitchFor2dImage(device->toHandle(), width, height, 1, &rowPitch);
@@ -1988,8 +2015,6 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageCreatedWithDeviceUMSPitchedPtr
ASSERT_NE(nullptr, ssHeapInfo);
EXPECT_EQ(ssHeapInfo->surfaceStateOffset, deviceOffset);
auto allocData = device->getDriverHandle()->getSvmAllocsManager()->getSVMAlloc(ptr);
// Allocation in image is equal to allocation from USM memory
EXPECT_EQ(allocData->gpuAllocations.getGraphicsAllocation(device->getNEODevice()->getRootDeviceIndex()), imageHW->getAllocation());
// Allocation should not have bindless offset allocated
@@ -2046,7 +2071,7 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageViewCreatedWithDeviceUMSPitche
ret = context->freeMem(ptr);
}
HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageViewCreatedWithTheSameFormatThenImageViewHasCorrectImgInfo, ImageSupport) {
HWTEST2_P(ImageCreateUsmPool, GivenBindlessImageWhenImageViewCreatedWithTheSameFormatThenImageViewHasCorrectImgInfo, ImageSupport) {
const size_t width = 32;
const size_t height = 32;
const size_t depth = 1;
@@ -2065,6 +2090,10 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageViewCreatedWithTheSameFormatTh
&ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, ret);
auto allocData = device->getDriverHandle()->getSvmAllocsManager()->getSVMAlloc(ptr);
const auto gpuAddress = allocData->gpuAllocations.getDefaultGraphicsAllocation()->getGpuAddress();
const auto offset = ptrDiff(castToUint64(ptr), gpuAddress);
ze_image_pitched_exp_desc_t pitchedDesc = {};
pitchedDesc.stype = ZE_STRUCTURE_TYPE_PITCHED_IMAGE_EXP_DESC;
pitchedDesc.ptr = ptr; // USM device pointer
@@ -2097,6 +2126,7 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageViewCreatedWithTheSameFormatTh
EXPECT_EQ(imageHW->imgInfo.rowPitch, imageViewObject->getImageInfo().rowPitch);
EXPECT_NE(0u, imageViewObject->getImageInfo().rowPitch);
EXPECT_EQ(imageHW->imgInfo.offset, imageViewObject->getImageInfo().offset);
EXPECT_EQ(offset, imageViewObject->getImageInfo().offset);
EXPECT_EQ(imageHW->imgInfo.size, imageViewObject->getImageInfo().size);
EXPECT_NE(0u, imageViewObject->getImageInfo().size);
EXPECT_EQ(imageHW->imgInfo.linearStorage, imageViewObject->getImageInfo().linearStorage);
@@ -2106,6 +2136,8 @@ HWTEST2_F(ImageCreate, GivenBindlessImageWhenImageViewCreatedWithTheSameFormatTh
ret = context->freeMem(ptr);
}
INSTANTIATE_TEST_SUITE_P(UsmPoolDisabledEnabled, ImageCreateUsmPool, ::testing::Values(0, 2));
HWTEST2_F(ImageCreate, GivenBindlessImageWhenInitializedThenSurfaceStateCopiedToSSH, ImageSupport) {
const size_t width = 32;
const size_t height = 32;