|
5 | 5 | * |
6 | 6 | */ |
7 | 7 |
|
| 8 | +#include "shared/source/device_binary_format/patchtokens_decoder.h" |
| 9 | +#include "shared/test/unit_test/device_binary_format/patchtokens_tests.h" |
| 10 | +#include "shared/test/unit_test/helpers/debug_manager_state_restore.h" |
8 | 11 | #include "shared/test/unit_test/mocks/mock_device.h" |
9 | 12 | #include "shared/test/unit_test/mocks/mock_graphics_allocation.h" |
10 | 13 |
|
11 | 14 | #include "opencl/source/program/kernel_info.h" |
| 15 | +#include "opencl/source/program/kernel_info_from_patchtokens.h" |
12 | 16 | #include "test.h" |
13 | 17 |
|
14 | 18 | #include "level_zero/core/source/image/image_format_desc_helper.h" |
15 | 19 | #include "level_zero/core/source/image/image_hw.h" |
| 20 | +#include "level_zero/core/source/kernel/kernel_hw.h" |
16 | 21 | #include "level_zero/core/source/module/module_imp.h" |
17 | 22 | #include "level_zero/core/source/sampler/sampler_hw.h" |
18 | 23 | #include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" |
|
21 | 26 | #include "level_zero/core/test/unit_tests/mocks/mock_kernel.h" |
22 | 27 | #include "level_zero/core/test/unit_tests/mocks/mock_module.h" |
23 | 28 |
|
| 29 | +void NEO::populateKernelDescriptor(KernelDescriptor &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes); |
| 30 | + |
24 | 31 | namespace L0 { |
25 | 32 | namespace ult { |
26 | 33 |
|
@@ -573,5 +580,215 @@ TEST_F(KernelIsaTests, givenGlobalBuffersWhenCreatingKernelImmutableDataThenBuff |
573 | 580 | EXPECT_EQ(1, std::count(resCont.begin(), resCont.end(), &globalConstBuffer)); |
574 | 581 | } |
575 | 582 |
|
| 583 | +using KernelImpPatchBindlessTest = Test<ModuleFixture>; |
| 584 | + |
| 585 | +TEST_F(KernelImpPatchBindlessTest, GivenKernelImpWhenPatchBindlessOffsetCalledThenOffsetPatchedCorrectly) { |
| 586 | + Mock<Kernel> kernel; |
| 587 | + WhiteBox<::L0::DeviceImp> mockDevice; |
| 588 | + mockDevice.neoDevice = neoDevice; |
| 589 | + neoDevice->incRefInternal(); |
| 590 | + neoDevice->bindlessHeapHelper.reset(new NEO::BindlessHeapsHelper(neoDevice->getMemoryManager(), neoDevice->getNumAvailableDevices() > 1, neoDevice->getRootDeviceIndex())); |
| 591 | + Mock<Module> mockModule(&mockDevice, nullptr); |
| 592 | + kernel.module = &mockModule; |
| 593 | + NEO::MockGraphicsAllocation alloc; |
| 594 | + uint32_t bindless = 0x40; |
| 595 | + auto &hwHelper = NEO::HwHelper::get(device->getHwInfo().platform.eRenderCoreFamily); |
| 596 | + size_t size = hwHelper.getRenderSurfaceStateSize(); |
| 597 | + auto expectedSsInHeap = device->getNEODevice()->getBindlessHeapsHelper()->allocateSSInHeap(size, &alloc, NEO::BindlessHeapsHelper::GLOBAL_SSH); |
| 598 | + auto patchLocation = ptrOffset(kernel.getCrossThreadData(), bindless); |
| 599 | + auto patchValue = hwHelper.getBindlessSurfaceExtendedMessageDescriptorValue(static_cast<uint32_t>(expectedSsInHeap.surfaceStateOffset)); |
| 600 | + |
| 601 | + auto ssPtr = kernel.patchBindlessSurfaceState(&alloc, bindless); |
| 602 | + |
| 603 | + EXPECT_EQ(ssPtr, expectedSsInHeap.ssPtr); |
| 604 | + EXPECT_TRUE(memcmp(const_cast<uint8_t *>(patchLocation), &patchValue, sizeof(patchValue)) == 0); |
| 605 | + EXPECT_TRUE(std::find(kernel.getResidencyContainer().begin(), kernel.getResidencyContainer().end(), expectedSsInHeap.heapAllocation) != kernel.getResidencyContainer().end()); |
| 606 | +} |
| 607 | + |
| 608 | +HWTEST2_F(KernelImpPatchBindlessTest, GivenKernelImpWhenSetSurfaceStateBindlessThenSurfaceStateUpdated, MatchAny) { |
| 609 | + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; |
| 610 | + |
| 611 | + ze_kernel_desc_t desc = {}; |
| 612 | + desc.pKernelName = kernelName.c_str(); |
| 613 | + |
| 614 | + WhiteBoxKernelHw<gfxCoreFamily> mockKernel; |
| 615 | + mockKernel.module = module.get(); |
| 616 | + mockKernel.initialize(&desc); |
| 617 | + auto &arg = const_cast<NEO::ArgDescPointer &>(mockKernel.kernelImmData->getDescriptor().payloadMappings.explicitArgs[0].template as<NEO::ArgDescPointer>()); |
| 618 | + arg.bindless = 0x40; |
| 619 | + arg.bindful = undefined<SurfaceStateHeapOffset>; |
| 620 | + |
| 621 | + neoDevice->bindlessHeapHelper.reset(new NEO::BindlessHeapsHelper(neoDevice->getMemoryManager(), neoDevice->getNumAvailableDevices() > 1, neoDevice->getRootDeviceIndex())); |
| 622 | + |
| 623 | + auto &hwHelper = NEO::HwHelper::get(device->getHwInfo().platform.eRenderCoreFamily); |
| 624 | + size_t size = hwHelper.getRenderSurfaceStateSize(); |
| 625 | + uint64_t gpuAddress = 0x2000; |
| 626 | + void *buffer = reinterpret_cast<void *>(gpuAddress); |
| 627 | + |
| 628 | + NEO::MockGraphicsAllocation mockAllocation(buffer, gpuAddress, size); |
| 629 | + auto expectedSsInHeap = device->getNEODevice()->getBindlessHeapsHelper()->allocateSSInHeap(size, &mockAllocation, NEO::BindlessHeapsHelper::GLOBAL_SSH); |
| 630 | + |
| 631 | + memset(expectedSsInHeap.ssPtr, 0, size); |
| 632 | + auto surfaceStateBefore = *reinterpret_cast<RENDER_SURFACE_STATE *>(expectedSsInHeap.ssPtr); |
| 633 | + mockKernel.setBufferSurfaceState(0, buffer, &mockAllocation); |
| 634 | + |
| 635 | + auto surfaceStateAfter = *reinterpret_cast<RENDER_SURFACE_STATE *>(expectedSsInHeap.ssPtr); |
| 636 | + |
| 637 | + EXPECT_FALSE(memcmp(&surfaceStateAfter, &surfaceStateBefore, size) == 0); |
| 638 | +} |
| 639 | + |
| 640 | +HWTEST2_F(KernelImpPatchBindlessTest, GivenKernelImpWhenSetSurfaceStateBindfulThenSurfaceStateNotUpdated, MatchAny) { |
| 641 | + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; |
| 642 | + ze_kernel_desc_t desc = {}; |
| 643 | + desc.pKernelName = kernelName.c_str(); |
| 644 | + |
| 645 | + WhiteBoxKernelHw<gfxCoreFamily> mockKernel; |
| 646 | + mockKernel.module = module.get(); |
| 647 | + mockKernel.initialize(&desc); |
| 648 | + |
| 649 | + auto &arg = const_cast<NEO::ArgDescPointer &>(mockKernel.kernelImmData->getDescriptor().payloadMappings.explicitArgs[0].template as<NEO::ArgDescPointer>()); |
| 650 | + arg.bindless = undefined<CrossThreadDataOffset>; |
| 651 | + arg.bindful = 0x40; |
| 652 | + |
| 653 | + neoDevice->bindlessHeapHelper.reset(new NEO::BindlessHeapsHelper(neoDevice->getMemoryManager(), neoDevice->getNumAvailableDevices() > 1, neoDevice->getRootDeviceIndex())); |
| 654 | + |
| 655 | + auto &hwHelper = NEO::HwHelper::get(device->getHwInfo().platform.eRenderCoreFamily); |
| 656 | + size_t size = hwHelper.getRenderSurfaceStateSize(); |
| 657 | + uint64_t gpuAddress = 0x2000; |
| 658 | + void *buffer = reinterpret_cast<void *>(gpuAddress); |
| 659 | + |
| 660 | + NEO::MockGraphicsAllocation mockAllocation(buffer, gpuAddress, size); |
| 661 | + auto expectedSsInHeap = device->getNEODevice()->getBindlessHeapsHelper()->allocateSSInHeap(size, &mockAllocation, NEO::BindlessHeapsHelper::GLOBAL_SSH); |
| 662 | + |
| 663 | + memset(expectedSsInHeap.ssPtr, 0, size); |
| 664 | + auto surfaceStateBefore = *reinterpret_cast<RENDER_SURFACE_STATE *>(expectedSsInHeap.ssPtr); |
| 665 | + mockKernel.setBufferSurfaceState(0, buffer, &mockAllocation); |
| 666 | + |
| 667 | + auto surfaceStateAfter = *reinterpret_cast<RENDER_SURFACE_STATE *>(expectedSsInHeap.ssPtr); |
| 668 | + |
| 669 | + EXPECT_TRUE(memcmp(&surfaceStateAfter, &surfaceStateBefore, size) == 0); |
| 670 | +} |
| 671 | + |
| 672 | +struct MyMockKernel : public Mock<Kernel> { |
| 673 | + void setBufferSurfaceState(uint32_t argIndex, void *address, NEO::GraphicsAllocation *alloc) override { |
| 674 | + setSurfaceStateCalled = true; |
| 675 | + } |
| 676 | + bool setSurfaceStateCalled = false; |
| 677 | +}; |
| 678 | + |
| 679 | +TEST_F(KernelImpPatchBindlessTest, GivenValidBindlessOffsetWhenSetArgBufferWithAllocThensetBufferSurfaceStateCalled) { |
| 680 | + ze_kernel_desc_t desc = {}; |
| 681 | + desc.pKernelName = kernelName.c_str(); |
| 682 | + MyMockKernel mockKernel; |
| 683 | + |
| 684 | + mockKernel.module = module.get(); |
| 685 | + mockKernel.initialize(&desc); |
| 686 | + |
| 687 | + auto &arg = const_cast<NEO::ArgDescPointer &>(mockKernel.kernelImmData->getDescriptor().payloadMappings.explicitArgs[0].as<NEO::ArgDescPointer>()); |
| 688 | + arg.bindless = 0x40; |
| 689 | + arg.bindful = undefined<SurfaceStateHeapOffset>; |
| 690 | + |
| 691 | + NEO::MockGraphicsAllocation alloc; |
| 692 | + |
| 693 | + mockKernel.setArgBufferWithAlloc(0, 0x1234, &alloc); |
| 694 | + |
| 695 | + EXPECT_TRUE(mockKernel.setSurfaceStateCalled); |
| 696 | +} |
| 697 | + |
| 698 | +TEST_F(KernelImpPatchBindlessTest, GivenValidBindfulOffsetWhenSetArgBufferWithAllocThensetBufferSurfaceStateCalled) { |
| 699 | + ze_kernel_desc_t desc = {}; |
| 700 | + desc.pKernelName = kernelName.c_str(); |
| 701 | + MyMockKernel mockKernel; |
| 702 | + |
| 703 | + mockKernel.module = module.get(); |
| 704 | + mockKernel.initialize(&desc); |
| 705 | + |
| 706 | + auto &arg = const_cast<NEO::ArgDescPointer &>(mockKernel.kernelImmData->getDescriptor().payloadMappings.explicitArgs[0].as<NEO::ArgDescPointer>()); |
| 707 | + arg.bindless = undefined<CrossThreadDataOffset>; |
| 708 | + arg.bindful = 0x40; |
| 709 | + |
| 710 | + NEO::MockGraphicsAllocation alloc; |
| 711 | + |
| 712 | + mockKernel.setArgBufferWithAlloc(0, 0x1234, &alloc); |
| 713 | + |
| 714 | + EXPECT_TRUE(mockKernel.setSurfaceStateCalled); |
| 715 | +} |
| 716 | + |
| 717 | +TEST_F(KernelImpPatchBindlessTest, GivenUndefiedBidfulAndBindlesstOffsetWhenSetArgBufferWithAllocThenSetBufferSurfaceStateIsNotCalled) { |
| 718 | + ze_kernel_desc_t desc = {}; |
| 719 | + desc.pKernelName = kernelName.c_str(); |
| 720 | + MyMockKernel mockKernel; |
| 721 | + |
| 722 | + mockKernel.module = module.get(); |
| 723 | + mockKernel.initialize(&desc); |
| 724 | + |
| 725 | + auto &arg = const_cast<NEO::ArgDescPointer &>(mockKernel.kernelImmData->getDescriptor().payloadMappings.explicitArgs[0].as<NEO::ArgDescPointer>()); |
| 726 | + arg.bindless = undefined<CrossThreadDataOffset>; |
| 727 | + arg.bindful = undefined<SurfaceStateHeapOffset>; |
| 728 | + |
| 729 | + NEO::MockGraphicsAllocation alloc; |
| 730 | + |
| 731 | + mockKernel.setArgBufferWithAlloc(0, 0x1234, &alloc); |
| 732 | + |
| 733 | + EXPECT_FALSE(mockKernel.setSurfaceStateCalled); |
| 734 | +} |
| 735 | +template <GFXCORE_FAMILY gfxCoreFamily> |
| 736 | +struct MyMockImage : public WhiteBox<::L0::ImageCoreFamily<gfxCoreFamily>> { |
| 737 | + //MyMockImage() : WhiteBox<::L0::ImageCoreFamily<gfxCoreFamily>>(); |
| 738 | + void copySurfaceStateToSSH(void *surfaceStateHeap, const uint32_t surfaceStateOffset) override { |
| 739 | + passedSurfaceStateHeap = surfaceStateHeap; |
| 740 | + passedSurfaceStateOffset = surfaceStateOffset; |
| 741 | + } |
| 742 | + void *passedSurfaceStateHeap = nullptr; |
| 743 | + uint32_t passedSurfaceStateOffset = 0; |
| 744 | +}; |
| 745 | + |
| 746 | +HWTEST2_F(SetKernelArg, givenImageAndBindlessKernelWhenSetArgImageThenCopySurfaceStateToSSHCalledWithCorrectArgs, ImageSupport) { |
| 747 | + createKernel(); |
| 748 | + |
| 749 | + neoDevice->bindlessHeapHelper.reset(new NEO::BindlessHeapsHelper(neoDevice->getMemoryManager(), neoDevice->getNumAvailableDevices() > 1, neoDevice->getRootDeviceIndex())); |
| 750 | + auto &imageArg = const_cast<NEO::ArgDescImage &>(kernel->kernelImmData->getDescriptor().payloadMappings.explicitArgs[3].template as<NEO::ArgDescImage>()); |
| 751 | + auto &addressingMode = kernel->kernelImmData->getDescriptor().kernelAttributes.imageAddressingMode; |
| 752 | + const_cast<NEO::KernelDescriptor::AddressingMode &>(addressingMode) = NEO::KernelDescriptor::Bindless; |
| 753 | + imageArg.bindless = 0x0; |
| 754 | + imageArg.bindful = undefined<SurfaceStateHeapOffset>; |
| 755 | + ze_image_desc_t desc = {}; |
| 756 | + auto &hwHelper = NEO::HwHelper::get(neoDevice->getHardwareInfo().platform.eRenderCoreFamily); |
| 757 | + auto surfaceStateSize = hwHelper.getRenderSurfaceStateSize(); |
| 758 | + |
| 759 | + auto imageHW = std::make_unique<MyMockImage<gfxCoreFamily>>(); |
| 760 | + auto ret = imageHW->initialize(device, &desc); |
| 761 | + auto handle = imageHW->toHandle(); |
| 762 | + ASSERT_EQ(ZE_RESULT_SUCCESS, ret); |
| 763 | + |
| 764 | + auto expectedSsInHeap = neoDevice->bindlessHeapHelper->allocateSSInHeap(surfaceStateSize, imageHW->getAllocation(), BindlessHeapsHelper::BindlesHeapType::GLOBAL_SSH); |
| 765 | + |
| 766 | + kernel->setArgImage(3, sizeof(imageHW.get()), &handle); |
| 767 | + |
| 768 | + EXPECT_EQ(imageHW->passedSurfaceStateHeap, expectedSsInHeap.ssPtr); |
| 769 | + EXPECT_EQ(imageHW->passedSurfaceStateOffset, 0u); |
| 770 | +} |
| 771 | + |
| 772 | +HWTEST2_F(SetKernelArg, givenImageAndBindfulKernelWhenSetArgImageThenCopySurfaceStateToSSHCalledWithCorrectArgs, ImageSupport) { |
| 773 | + createKernel(); |
| 774 | + |
| 775 | + auto &imageArg = const_cast<NEO::ArgDescImage &>(kernel->kernelImmData->getDescriptor().payloadMappings.explicitArgs[3].template as<NEO::ArgDescImage>()); |
| 776 | + auto addressingMode = const_cast<NEO::KernelDescriptor::AddressingMode &>(kernel->kernelImmData->getDescriptor().kernelAttributes.imageAddressingMode); |
| 777 | + addressingMode = NEO::KernelDescriptor::Bindful; |
| 778 | + imageArg.bindless = undefined<CrossThreadDataOffset>; |
| 779 | + imageArg.bindful = 0x40; |
| 780 | + ze_image_desc_t desc = {}; |
| 781 | + |
| 782 | + auto imageHW = std::make_unique<MyMockImage<gfxCoreFamily>>(); |
| 783 | + auto ret = imageHW->initialize(device, &desc); |
| 784 | + auto handle = imageHW->toHandle(); |
| 785 | + ASSERT_EQ(ZE_RESULT_SUCCESS, ret); |
| 786 | + |
| 787 | + kernel->setArgImage(3, sizeof(imageHW.get()), &handle); |
| 788 | + |
| 789 | + EXPECT_EQ(imageHW->passedSurfaceStateHeap, kernel->getSurfaceStateHeapData()); |
| 790 | + EXPECT_EQ(imageHW->passedSurfaceStateOffset, imageArg.bindful); |
| 791 | +} |
| 792 | + |
576 | 793 | } // namespace ult |
577 | 794 | } // namespace L0 |
0 commit comments