mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-03 06:49:52 +08:00
feature: bindless addressing for images
- program surface states for redescribed images correctly. Image copy to/from memory are using redescribed surface states, - refactor state base address programming - program address and size together, set max size at the beginning due to lack of Enable flag - set GpuBase in WddmAllocation when external heap is used - return max ssh required size from kernelInfo or based on stateful args Related-To: NEO-7063 Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
94bfc3418b
commit
8435160db4
@@ -549,7 +549,35 @@ ze_result_t KernelImp::setArgRedescribedImage(uint32_t argIndex, ze_image_handle
|
||||
}
|
||||
|
||||
const auto image = Image::fromHandle(argVal);
|
||||
image->copyRedescribedSurfaceStateToSSH(surfaceStateHeapData.get(), arg.bindful);
|
||||
|
||||
if (kernelImmData->getDescriptor().kernelAttributes.imageAddressingMode == NEO::KernelDescriptor::Bindless) {
|
||||
|
||||
NEO::BindlessHeapsHelper *bindlessHeapsHelper = this->module->getDevice()->getNEODevice()->getBindlessHeapsHelper();
|
||||
auto &gfxCoreHelper = this->module->getDevice()->getGfxCoreHelper();
|
||||
const auto surfaceStateSize = gfxCoreHelper.getRenderSurfaceStateSize();
|
||||
if (bindlessHeapsHelper) {
|
||||
|
||||
if (!this->module->getDevice()->getNEODevice()->getMemoryManager()->allocateBindlessSlot(image->getAllocation())) {
|
||||
return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
auto ssInHeap = image->getAllocation()->getBindlessInfo();
|
||||
auto patchLocation = ptrOffset(getCrossThreadData(), arg.bindless);
|
||||
// redescribed image's surface state is after image's state
|
||||
auto bindlessSlotOffset = ssInHeap.surfaceStateOffset + surfaceStateSize;
|
||||
auto patchValue = gfxCoreHelper.getBindlessSurfaceExtendedMessageDescriptorValue(static_cast<uint32_t>(bindlessSlotOffset));
|
||||
patchWithRequiredSize(const_cast<uint8_t *>(patchLocation), sizeof(patchValue), patchValue);
|
||||
|
||||
image->copyRedescribedSurfaceStateToSSH(ptrOffset(ssInHeap.ssPtr, surfaceStateSize), 0u);
|
||||
this->residencyContainer.push_back(ssInHeap.heapAllocation);
|
||||
} else {
|
||||
|
||||
auto ssPtr = ptrOffset(surfaceStateHeapData.get(), getSurfaceStateIndexForBindlessOffset(arg.bindless) * surfaceStateSize);
|
||||
image->copyRedescribedSurfaceStateToSSH(ssPtr, 0u);
|
||||
}
|
||||
} else {
|
||||
image->copyRedescribedSurfaceStateToSSH(surfaceStateHeapData.get(), arg.bindful);
|
||||
}
|
||||
residencyContainer[argIndex] = image->getAllocation();
|
||||
|
||||
return ZE_RESULT_SUCCESS;
|
||||
|
||||
@@ -2433,8 +2433,17 @@ struct MyMockImage : public WhiteBox<::L0::ImageCoreFamily<gfxCoreFamily>> {
|
||||
passedSurfaceStateHeap = surfaceStateHeap;
|
||||
passedSurfaceStateOffset = surfaceStateOffset;
|
||||
}
|
||||
|
||||
void copyRedescribedSurfaceStateToSSH(void *surfaceStateHeap, const uint32_t surfaceStateOffset) override {
|
||||
passedRedescribedSurfaceStateHeap = surfaceStateHeap;
|
||||
passedRedescribedSurfaceStateOffset = surfaceStateOffset;
|
||||
}
|
||||
|
||||
void *passedSurfaceStateHeap = nullptr;
|
||||
uint32_t passedSurfaceStateOffset = 0;
|
||||
|
||||
void *passedRedescribedSurfaceStateHeap = nullptr;
|
||||
uint32_t passedRedescribedSurfaceStateOffset = 0;
|
||||
};
|
||||
|
||||
HWTEST2_F(SetKernelArg, givenImageAndBindlessKernelWhenSetArgImageThenCopySurfaceStateToSSHCalledWithCorrectArgs, ImageSupport) {
|
||||
@@ -2500,6 +2509,110 @@ HWTEST2_F(SetKernelArg, givenBindlessKernelAndNoAvailableSpaceOnSshWhenSetArgIma
|
||||
EXPECT_EQ(nullptr, bindlessInfo.heapAllocation);
|
||||
}
|
||||
|
||||
HWTEST2_F(SetKernelArg, givenImageBindlessKernelAndGlobalBindlessHelperWhenSetArgRedescribedImageCalledThenCopySurfaceStateToSSHCalledWithCorrectArgs, ImageSupport) {
|
||||
createKernel();
|
||||
|
||||
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]->createBindlessHeapsHelper(neoDevice->getMemoryManager(),
|
||||
neoDevice->getNumGenericSubDevices() > 1,
|
||||
neoDevice->getRootDeviceIndex(),
|
||||
neoDevice->getDeviceBitfield());
|
||||
auto &imageArg = const_cast<NEO::ArgDescImage &>(kernel->kernelImmData->getDescriptor().payloadMappings.explicitArgs[3].template as<NEO::ArgDescImage>());
|
||||
auto &addressingMode = kernel->kernelImmData->getDescriptor().kernelAttributes.imageAddressingMode;
|
||||
const_cast<NEO::KernelDescriptor::AddressingMode &>(addressingMode) = NEO::KernelDescriptor::Bindless;
|
||||
imageArg.bindless = 0x0;
|
||||
imageArg.bindful = undefined<SurfaceStateHeapOffset>;
|
||||
ze_image_desc_t desc = {};
|
||||
desc.stype = ZE_STRUCTURE_TYPE_IMAGE_DESC;
|
||||
|
||||
auto imageHW = std::make_unique<MyMockImage<gfxCoreFamily>>();
|
||||
auto ret = imageHW->initialize(device, &desc);
|
||||
auto handle = imageHW->toHandle();
|
||||
ASSERT_EQ(ZE_RESULT_SUCCESS, ret);
|
||||
|
||||
ret = kernel->setArgRedescribedImage(3, handle);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, ret);
|
||||
|
||||
auto &gfxCoreHelper = neoDevice->getGfxCoreHelper();
|
||||
auto surfaceStateSize = gfxCoreHelper.getRenderSurfaceStateSize();
|
||||
|
||||
auto expectedSsInHeap = imageHW->getAllocation()->getBindlessInfo();
|
||||
EXPECT_EQ(imageHW->passedRedescribedSurfaceStateHeap, ptrOffset(expectedSsInHeap.ssPtr, surfaceStateSize));
|
||||
EXPECT_EQ(imageHW->passedRedescribedSurfaceStateOffset, 0u);
|
||||
}
|
||||
|
||||
HWTEST2_F(SetKernelArg, givenImageAndBindlessKernelWhenSetArgRedescribedImageCalledThenCopySurfaceStateToSSHCalledWithCorrectArgs, ImageSupport) {
|
||||
Mock<Module> mockModule(this->device, nullptr);
|
||||
Mock<KernelImp> mockKernel;
|
||||
mockKernel.module = &mockModule;
|
||||
|
||||
mockKernel.descriptor.kernelAttributes.bufferAddressingMode = NEO::KernelDescriptor::BindlessAndStateless;
|
||||
mockKernel.descriptor.kernelAttributes.imageAddressingMode = NEO::KernelDescriptor::Bindless;
|
||||
|
||||
auto argDescriptor = NEO::ArgDescriptor(NEO::ArgDescriptor::ArgTImage);
|
||||
argDescriptor.as<NEO::ArgDescImage>() = NEO::ArgDescImage();
|
||||
argDescriptor.as<NEO::ArgDescImage>().bindful = NEO::undefined<NEO::SurfaceStateHeapOffset>;
|
||||
argDescriptor.as<NEO::ArgDescImage>().bindless = 0x0;
|
||||
mockKernel.crossThreadData = std::make_unique<uint8_t[]>(4 * sizeof(uint64_t));
|
||||
mockKernel.crossThreadDataSize = 4 * sizeof(uint64_t);
|
||||
mockKernel.descriptor.payloadMappings.explicitArgs.push_back(argDescriptor);
|
||||
auto &gfxCoreHelper = neoDevice->getGfxCoreHelper();
|
||||
auto surfaceStateSize = gfxCoreHelper.getRenderSurfaceStateSize();
|
||||
|
||||
mockKernel.surfaceStateHeapData = std::make_unique<uint8_t[]>(surfaceStateSize);
|
||||
mockKernel.descriptor.initBindlessOffsetToSurfaceState();
|
||||
mockKernel.residencyContainer.resize(1);
|
||||
|
||||
ze_image_desc_t desc = {};
|
||||
desc.stype = ZE_STRUCTURE_TYPE_IMAGE_DESC;
|
||||
|
||||
auto imageHW = std::make_unique<MyMockImage<gfxCoreFamily>>();
|
||||
auto ret = imageHW->initialize(device, &desc);
|
||||
auto handle = imageHW->toHandle();
|
||||
ASSERT_EQ(ZE_RESULT_SUCCESS, ret);
|
||||
|
||||
ret = mockKernel.setArgRedescribedImage(0, handle);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, ret);
|
||||
|
||||
auto expectedSsInHeap = ptrOffset(mockKernel.surfaceStateHeapData.get(), mockKernel.kernelImmData->getDescriptor().getBindlessOffsetToSurfaceState().find(0x0)->second * surfaceStateSize);
|
||||
EXPECT_EQ(imageHW->passedRedescribedSurfaceStateHeap, expectedSsInHeap);
|
||||
EXPECT_EQ(imageHW->passedRedescribedSurfaceStateOffset, 0u);
|
||||
}
|
||||
|
||||
HWTEST2_F(SetKernelArg, givenBindlessKernelAndNoAvailableSpaceOnSshWhenSetArgRedescribedImageCalledThenOutOfMemoryErrorReturned, ImageSupport) {
|
||||
createKernel();
|
||||
|
||||
auto mockMemManager = static_cast<MockMemoryManager *>(neoDevice->getMemoryManager());
|
||||
auto bindlessHelper = new MockBindlesHeapsHelper(mockMemManager,
|
||||
neoDevice->getNumGenericSubDevices() > 1,
|
||||
neoDevice->getRootDeviceIndex(),
|
||||
neoDevice->getDeviceBitfield());
|
||||
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]->bindlessHeapsHelper.reset(bindlessHelper);
|
||||
|
||||
auto &imageArg = const_cast<NEO::ArgDescImage &>(kernel->kernelImmData->getDescriptor().payloadMappings.explicitArgs[3].template as<NEO::ArgDescImage>());
|
||||
auto &addressingMode = kernel->kernelImmData->getDescriptor().kernelAttributes.imageAddressingMode;
|
||||
const_cast<NEO::KernelDescriptor::AddressingMode &>(addressingMode) = NEO::KernelDescriptor::Bindless;
|
||||
imageArg.bindless = 0x0;
|
||||
imageArg.bindful = undefined<SurfaceStateHeapOffset>;
|
||||
ze_image_desc_t desc = {};
|
||||
desc.stype = ZE_STRUCTURE_TYPE_IMAGE_DESC;
|
||||
|
||||
auto imageHW = std::make_unique<MyMockImage<gfxCoreFamily>>();
|
||||
auto ret = imageHW->initialize(device, &desc);
|
||||
auto handle = imageHW->toHandle();
|
||||
ASSERT_EQ(ZE_RESULT_SUCCESS, ret);
|
||||
|
||||
mockMemManager->failInDevicePool = true;
|
||||
mockMemManager->failAllocateSystemMemory = true;
|
||||
bindlessHelper->globalSsh->getSpace(bindlessHelper->globalSsh->getAvailableSpace());
|
||||
|
||||
ret = kernel->setArgRedescribedImage(3, handle);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, ret);
|
||||
|
||||
auto bindlessInfo = imageHW->getAllocation()->getBindlessInfo();
|
||||
EXPECT_EQ(nullptr, bindlessInfo.ssPtr);
|
||||
EXPECT_EQ(nullptr, bindlessInfo.heapAllocation);
|
||||
}
|
||||
|
||||
HWTEST2_F(SetKernelArg, givenBindlessKernelAndNoAvailableSpaceOnSshWhenSetArgBufferCalledThenOutOfMemoryErrorReturned, MatchAny) {
|
||||
|
||||
auto mockMemManager = static_cast<MockMemoryManager *>(neoDevice->getMemoryManager());
|
||||
|
||||
Reference in New Issue
Block a user