diff --git a/level_zero/core/test/unit_tests/gen9/CMakeLists.txt b/level_zero/core/test/unit_tests/gen9/CMakeLists.txt index 73d4106147..9513818299 100644 --- a/level_zero/core/test/unit_tests/gen9/CMakeLists.txt +++ b/level_zero/core/test/unit_tests/gen9/CMakeLists.txt @@ -7,8 +7,10 @@ if(TESTS_GEN9) target_sources(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdlist_gen9.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdlist_append_launch_kernel_gen9.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdlist_append_range_barrier_gen9.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdlist_create_gen9.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdlist_gen9.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_enqueuecommandlist_gen9.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_gen9.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_device_gen9.cpp diff --git a/level_zero/core/test/unit_tests/gen9/test_cmdlist_append_range_barrier_gen9.cpp b/level_zero/core/test/unit_tests/gen9/test_cmdlist_append_range_barrier_gen9.cpp new file mode 100644 index 0000000000..cd81b8ff03 --- /dev/null +++ b/level_zero/core/test/unit_tests/gen9/test_cmdlist_append_range_barrier_gen9.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/common/cmd_parse/gen_cmd_parse.h" +#include "shared/test/common/test_macros/test.h" + +#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" +#include "level_zero/core/test/unit_tests/mocks/mock_cmdlist.h" + +namespace L0 { +namespace ult { + +using CommandListAppendGen9 = Test; + +TEST(CommandListAppendMemoryRangesBarrier, WhenAppendingMemoryRangesBarrierThenSuccessIsReturned) { + MockCommandList commandList; + + uint32_t numRanges = 1; + const size_t pRangeSizes = 1; + const char *ranges[pRangeSizes]; + const void **pRanges = reinterpret_cast(&ranges[0]); + + auto result = zeCommandListAppendMemoryRangesBarrier(commandList.toHandle(), + numRanges, &pRangeSizes, + pRanges, nullptr, 0, + nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +HWTEST2_F(CommandListAppendGen9, WhenAppendingMemoryRangesBarrierThenPipeControlAddedToCommandStream, IsGen9) { + uint32_t numRanges = 1; + const size_t pRangeSizes = 1; + const char *ranges[pRangeSizes]; + const void **pRanges = reinterpret_cast(&ranges[0]); + + auto commandList = new CommandListCoreFamily(); + bool ret = commandList->initialize(device, NEO::EngineGroupType::RenderCompute, 0u); + ASSERT_FALSE(ret); + auto usedSpaceBefore = + commandList->commandContainer.getCommandStream()->getUsed(); + commandList->appendMemoryRangesBarrier(numRanges, &pRangeSizes, pRanges, + nullptr, 0, nullptr); + auto usedSpaceAfter = + commandList->commandContainer.getCommandStream()->getUsed(); + ASSERT_GT(usedSpaceAfter, usedSpaceBefore); + + GenCmdList cmdList; + ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer( + cmdList, + ptrOffset( + commandList->commandContainer.getCommandStream()->getCpuBase(), 0), + usedSpaceAfter)); + + using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL; + auto itorPC = find(cmdList.begin(), cmdList.end()); + ASSERT_NE(cmdList.end(), itorPC); + + auto cmd = genCmdCast(*itorPC); + EXPECT_TRUE(cmd->getCommandStreamerStallEnable()); + EXPECT_TRUE(cmd->getDcFlushEnable()); + + commandList->destroy(); +} + +HWTEST2_F(CommandListAppendGen9, givenSignalEventWhenAppendingMemoryRangesBarrierThenSecondPipeControlAddedToCommandStreamForCompletion, IsGen9) { + uint32_t numRanges = 1; + const size_t pRangeSizes = 1; + const char *ranges[pRangeSizes]; + const void **pRanges = reinterpret_cast(&ranges[0]); + + auto commandList = new CommandListCoreFamily(); + bool ret = commandList->initialize(device, NEO::EngineGroupType::RenderCompute, 0u); + ASSERT_FALSE(ret); + ze_event_pool_desc_t eventPoolDesc = { + ZE_STRUCTURE_TYPE_EVENT_POOL_DESC, + nullptr, + ZE_EVENT_POOL_FLAG_HOST_VISIBLE, + 1}; + + const ze_event_desc_t eventDesc = { + ZE_STRUCTURE_TYPE_EVENT_DESC, + nullptr, + 0, + ZE_EVENT_SCOPE_FLAG_HOST, + ZE_EVENT_SCOPE_FLAG_HOST}; + + ze_result_t result = ZE_RESULT_SUCCESS; + auto context = std::make_unique(device->getDriverHandle()); + auto hDevice = device->toHandle(); + auto eventPool = whiteboxCast(EventPool::create(device->getDriverHandle(), context.get(), 1, &hDevice, &eventPoolDesc, result)); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + auto event = whiteboxCast(Event::create(eventPool, &eventDesc, device)); + auto usedSpaceBefore = + commandList->commandContainer.getCommandStream()->getUsed(); + commandList->appendMemoryRangesBarrier(numRanges, &pRangeSizes, pRanges, + event->toHandle(), 0, nullptr); + auto usedSpaceAfter = commandList->commandContainer.getCommandStream()->getUsed(); + ASSERT_GT(usedSpaceAfter, usedSpaceBefore); + + // Ensure we have two pipe controls: one for barrier, one for signal + GenCmdList cmdList; + ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer( + cmdList, ptrOffset(commandList->commandContainer.getCommandStream()->getCpuBase(), 0), usedSpaceAfter)); + using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL; + auto itor = findAll(cmdList.begin(), cmdList.end()); + ASSERT_FALSE(itor.empty()); + ASSERT_LT(1, static_cast(itor.size())); + + delete event; + delete eventPool; + commandList->destroy(); +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/core/test/unit_tests/gen9/test_cmdlist_create_gen9.cpp b/level_zero/core/test/unit_tests/gen9/test_cmdlist_create_gen9.cpp new file mode 100644 index 0000000000..14b367b0cb --- /dev/null +++ b/level_zero/core/test/unit_tests/gen9/test_cmdlist_create_gen9.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/command_stream/linear_stream.h" +#include "shared/source/helpers/string.h" +#include "shared/source/indirect_heap/indirect_heap.h" +#include "shared/test/common/cmd_parse/gen_cmd_parse.h" +#include "shared/test/common/test_macros/test.h" + +#include "level_zero/core/source/event/event.h" +#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" +#include "level_zero/core/test/unit_tests/mocks/mock_cmdlist.h" +#include "level_zero/core/test/unit_tests/mocks/mock_kernel.h" + +#include + +namespace L0 { +namespace ult { +class CommandListCreateGen9 : public DeviceFixture, public testing::Test { + public: + void SetUp() override { + DeviceFixture::SetUp(); + + dispatchFunctionArguments.groupCountX = 1u; + dispatchFunctionArguments.groupCountY = 2u; + dispatchFunctionArguments.groupCountZ = 3u; + } + + void TearDown() override { + if (buffer) { + alignedFree(buffer); + } + for (auto ptr : isaBuffers) { + free(ptr); + } + + DeviceFixture::TearDown(); + } + + std::vector isaBuffers; + ze_group_count_t dispatchFunctionArguments; + void *buffer = nullptr; + + void initializeFunction(WhiteBox<::L0::Kernel> &function, + WhiteBox<::L0::KernelImmutableData> &functionData, + L0::Device *device) { + + uint32_t isaSize = 4096; + void *isaBuffer = malloc(isaSize); + isaBuffers.push_back(isaBuffer); + + functionData.device = device; + if (!buffer) { + buffer = alignedMalloc(isaSize, 64); + } + auto allocation = new NEO::GraphicsAllocation(0, NEO::AllocationType::INTERNAL_HOST_MEMORY, + buffer, reinterpret_cast(buffer), 0, isaSize, + MemoryPool::System4KBPages); + if (isaBuffer != nullptr) { + memcpy_s(allocation->getUnderlyingBuffer(), allocation->getUnderlyingBufferSize(), isaBuffer, isaSize); + } + functionData.isaGraphicsAllocation.reset(allocation); + + uint32_t crossThreadDataSize = 128; + + function.crossThreadData.reset(new uint8_t[crossThreadDataSize]); + function.crossThreadDataSize = crossThreadDataSize; + + uint32_t perThreadDataSize = 128; + + function.perThreadDataForWholeThreadGroup = static_cast(alignedMalloc(perThreadDataSize, 32)); + function.perThreadDataSize = perThreadDataSize; + + function.kernelImmData = &functionData; + } + void cleanupFunction(WhiteBox<::L0::KernelImmutableData> &functionData) { + functionData.isaGraphicsAllocation.reset(nullptr); + } +}; + +GEN9TEST_F(CommandListCreateGen9, WhenGettingCommandListPreemptionModeThenMatchesDevicePreemptionMode) { + ze_result_t returnValue; + auto commandList = whiteboxCast(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)); + + auto result = commandList->close(); + ASSERT_EQ(ZE_RESULT_SUCCESS, result); + + EXPECT_EQ(device->getDevicePreemptionMode(), commandList->getCommandListPreemptionMode()); + + delete commandList; +} + +GEN9TEST_F(CommandListCreateGen9, GivenDisabledMidThreadPreemptionWhenLaunchingKernelThenThreadGroupModeSet) { + WhiteBox<::L0::KernelImmutableData> funcInfoThreadGroupData = {}; + NEO::KernelDescriptor kernelDescriptor; + funcInfoThreadGroupData.kernelDescriptor = &kernelDescriptor; + WhiteBox<::L0::Kernel> functionThreadGroup; + + funcInfoThreadGroupData.kernelDescriptor->kernelAttributes.flags.requiresDisabledMidThreadPreemption = 1; + + initializeFunction(functionThreadGroup, funcInfoThreadGroupData, device); + + ze_result_t returnValue; + auto commandList = whiteboxCast(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)); + EXPECT_EQ(NEO::PreemptionMode::MidThread, commandList->getCommandListPreemptionMode()); + + commandList->appendLaunchKernel(functionThreadGroup.toHandle(), + &dispatchFunctionArguments, nullptr, 0, nullptr); + EXPECT_EQ(NEO::PreemptionMode::ThreadGroup, commandList->getCommandListPreemptionMode()); + + auto result = commandList->close(); + ASSERT_EQ(ZE_RESULT_SUCCESS, result); + + EXPECT_EQ(NEO::PreemptionMode::ThreadGroup, commandList->getCommandListPreemptionMode()); + cleanupFunction(funcInfoThreadGroupData); + delete commandList; +} + +GEN9TEST_F(CommandListCreateGen9, GivenUsesFencesForReadWriteImagesWhenLaunchingKernelThenMidBatchModeSet) { + WhiteBox<::L0::KernelImmutableData> funcInfoMidBatchData = {}; + NEO::KernelDescriptor kernelDescriptor; + funcInfoMidBatchData.kernelDescriptor = &kernelDescriptor; + WhiteBox<::L0::Kernel> functionMidBatch; + + funcInfoMidBatchData.kernelDescriptor->kernelAttributes.flags.requiresDisabledMidThreadPreemption = 1; + funcInfoMidBatchData.kernelDescriptor->kernelAttributes.flags.usesFencesForReadWriteImages = 1; + + device->getNEODevice()->getRootDeviceEnvironment().getMutableHardwareInfo()->workaroundTable.flags.waDisableLSQCROPERFforOCL = true; + + initializeFunction(functionMidBatch, funcInfoMidBatchData, device); + + ze_result_t returnValue; + auto commandList = whiteboxCast(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)); + EXPECT_EQ(NEO::PreemptionMode::MidThread, commandList->getCommandListPreemptionMode()); + + commandList->appendLaunchKernel(functionMidBatch.toHandle(), + &dispatchFunctionArguments, nullptr, 0, nullptr); + EXPECT_EQ(NEO::PreemptionMode::MidBatch, commandList->getCommandListPreemptionMode()); + + auto result = commandList->close(); + ASSERT_EQ(ZE_RESULT_SUCCESS, result); + + EXPECT_EQ(NEO::PreemptionMode::MidBatch, commandList->getCommandListPreemptionMode()); + cleanupFunction(funcInfoMidBatchData); + delete commandList; +} + +GEN9TEST_F(CommandListCreateGen9, WhenCommandListHasLowerPreemptionLevelThenDoNotIncreaseAgain) { + WhiteBox<::L0::KernelImmutableData> funcInfoThreadGroupData = {}; + NEO::KernelDescriptor kernelDescriptor; + funcInfoThreadGroupData.kernelDescriptor = &kernelDescriptor; + WhiteBox<::L0::Kernel> functionThreadGroup; + + funcInfoThreadGroupData.kernelDescriptor->kernelAttributes.flags.requiresDisabledMidThreadPreemption = 1; + + initializeFunction(functionThreadGroup, funcInfoThreadGroupData, device); + + WhiteBox<::L0::KernelImmutableData> funcInfoMidThreadData = {}; + NEO::KernelDescriptor kernelDescriptor2; + funcInfoMidThreadData.kernelDescriptor = &kernelDescriptor2; + + WhiteBox<::L0::Kernel> functionMidThread; + + initializeFunction(functionMidThread, funcInfoMidThreadData, device); + + ze_result_t returnValue; + auto commandList = whiteboxCast(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)); + EXPECT_EQ(NEO::PreemptionMode::MidThread, commandList->getCommandListPreemptionMode()); + + commandList->appendLaunchKernel(functionThreadGroup.toHandle(), + &dispatchFunctionArguments, nullptr, 0, nullptr); + EXPECT_EQ(NEO::PreemptionMode::ThreadGroup, commandList->getCommandListPreemptionMode()); + + commandList->appendLaunchKernel(functionMidThread.toHandle(), + &dispatchFunctionArguments, nullptr, 0, nullptr); + EXPECT_EQ(NEO::PreemptionMode::ThreadGroup, commandList->getCommandListPreemptionMode()); + + auto result = commandList->close(); + ASSERT_EQ(ZE_RESULT_SUCCESS, result); + + EXPECT_EQ(NEO::PreemptionMode::ThreadGroup, commandList->getCommandListPreemptionMode()); + cleanupFunction(funcInfoThreadGroupData); + cleanupFunction(funcInfoMidThreadData); + delete commandList; +} +} // namespace ult +} // namespace L0 diff --git a/level_zero/core/test/unit_tests/sources/cmdqueue/CMakeLists.txt b/level_zero/core/test/unit_tests/sources/cmdqueue/CMakeLists.txt index 0467ce30e4..67a61867db 100644 --- a/level_zero/core/test/unit_tests/sources/cmdqueue/CMakeLists.txt +++ b/level_zero/core/test/unit_tests/sources/cmdqueue/CMakeLists.txt @@ -9,6 +9,7 @@ target_sources(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_1.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_2.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_enqueue_cmdlist.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_enqueue_cmdlist_2.cpp ) add_subdirectories() diff --git a/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_enqueue_cmdlist_2.cpp b/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_enqueue_cmdlist_2.cpp new file mode 100644 index 0000000000..b668bb7a3f --- /dev/null +++ b/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_enqueue_cmdlist_2.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/common/cmd_parse/gen_cmd_parse.h" +#include "shared/test/common/helpers/unit_test_helper.h" +#include "shared/test/common/test_macros/test.h" + +#include "level_zero/core/source/fence/fence.h" +#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" +#include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h" +#include "level_zero/core/test/unit_tests/mocks/mock_fence.h" + +namespace L0 { +namespace ult { + +using CommandQueueExecuteCommandListsSimpleTest = Test; + +HWTEST2_F(CommandQueueExecuteCommandListsSimpleTest, GivenSynchronousModeWhenExecutingCommandListThenSynchronizeIsCalled, IsAtLeastSkl) { + ze_command_queue_desc_t desc; + desc.mode = ZE_COMMAND_QUEUE_MODE_SYNCHRONOUS; + auto mockCmdQ = new MockCommandQueueHw(device, neoDevice->getDefaultEngine().commandStreamReceiver, &desc); + mockCmdQ->initialize(false, false); + ze_result_t returnValue; + ze_command_list_handle_t commandLists[] = { + CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)->toHandle()}; + mockCmdQ->executeCommandLists(1, commandLists, nullptr, true); + EXPECT_EQ(mockCmdQ->synchronizedCalled, 1u); + CommandList::fromHandle(commandLists[0])->destroy(); + mockCmdQ->destroy(); +} + +HWTEST2_F(CommandQueueExecuteCommandListsSimpleTest, GivenSynchronousModeAndDeviceLostSynchronizeWhenExecutingCommandListThenSynchronizeIsCalledAndDeviceLostIsReturned, IsAtLeastSkl) { + ze_command_queue_desc_t desc; + desc.mode = ZE_COMMAND_QUEUE_MODE_SYNCHRONOUS; + + auto mockCmdQ = new MockCommandQueueHw(device, neoDevice->getDefaultEngine().commandStreamReceiver, &desc); + mockCmdQ->initialize(false, false); + mockCmdQ->synchronizeReturnValue = ZE_RESULT_ERROR_DEVICE_LOST; + + ze_result_t returnValue; + ze_command_list_handle_t commandLists[] = { + CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)->toHandle()}; + + const auto result = mockCmdQ->executeCommandLists(1, commandLists, nullptr, true); + EXPECT_EQ(mockCmdQ->synchronizedCalled, 1u); + EXPECT_EQ(ZE_RESULT_ERROR_DEVICE_LOST, result); + + CommandList::fromHandle(commandLists[0])->destroy(); + mockCmdQ->destroy(); +} + +HWTEST2_F(CommandQueueExecuteCommandListsSimpleTest, GivenAsynchronousModeWhenExecutingCommandListThenSynchronizeIsNotCalled, IsAtLeastSkl) { + ze_command_queue_desc_t desc; + desc.mode = ZE_COMMAND_QUEUE_MODE_ASYNCHRONOUS; + auto mockCmdQ = new MockCommandQueueHw(device, neoDevice->getDefaultEngine().commandStreamReceiver, &desc); + mockCmdQ->initialize(false, false); + ze_result_t returnValue; + ze_command_list_handle_t commandLists[] = { + CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)->toHandle()}; + mockCmdQ->executeCommandLists(1, commandLists, nullptr, true); + EXPECT_EQ(mockCmdQ->synchronizedCalled, 0u); + CommandList::fromHandle(commandLists[0])->destroy(); + mockCmdQ->destroy(); +} + +HWTEST2_F(CommandQueueExecuteCommandListsSimpleTest, whenUsingFenceThenLastPipeControlUpdatesFenceAllocation, IsAtLeastSkl) { + using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL; + using POST_SYNC_OPERATION = typename FamilyType::PIPE_CONTROL::POST_SYNC_OPERATION; + + ze_command_queue_desc_t queueDesc = {}; + ze_result_t returnValue; + queueDesc.mode = ZE_COMMAND_QUEUE_MODE_ASYNCHRONOUS; + auto commandQueue = whiteboxCast(CommandQueue::create(productFamily, device, neoDevice->getDefaultEngine().commandStreamReceiver, &queueDesc, false, false, returnValue)); + ASSERT_NE(nullptr, commandQueue->commandStream); + + ze_fence_desc_t fenceDesc = {}; + + auto fence = whiteboxCast(Fence::create(commandQueue, &fenceDesc)); + ze_fence_handle_t fenceHandle = fence->toHandle(); + + auto usedSpaceBefore = commandQueue->commandStream->getUsed(); + + ze_command_list_handle_t commandLists[] = { + CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)->toHandle(), + CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)->toHandle()}; + uint32_t numCommandLists = sizeof(commandLists) / sizeof(commandLists[0]); + auto result = commandQueue->executeCommandLists(numCommandLists, commandLists, fenceHandle, true); + + ASSERT_EQ(ZE_RESULT_SUCCESS, result); + + auto usedSpaceAfter = commandQueue->commandStream->getUsed(); + ASSERT_GT(usedSpaceAfter, usedSpaceBefore); + + GenCmdList cmdList; + ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer( + cmdList, ptrOffset(commandQueue->commandStream->getCpuBase(), 0), usedSpaceAfter)); + + auto pipeControls = findAll(cmdList.begin(), cmdList.end()); + size_t pipeControlsPostSyncNumber = 0u; + for (size_t i = 0; i < pipeControls.size(); i++) { + auto pipeControl = reinterpret_cast(*pipeControls[i]); + if (pipeControl->getPostSyncOperation() == POST_SYNC_OPERATION::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA) { + EXPECT_EQ(commandQueue->getCsr()->getTagAllocation()->getGpuAddress(), NEO::UnitTestHelper::getPipeControlPostSyncAddress(*pipeControl)); + EXPECT_EQ(fence->taskCount, pipeControl->getImmediateData()); + pipeControlsPostSyncNumber++; + } + } + EXPECT_EQ(1u, pipeControlsPostSyncNumber); + + for (auto i = 0u; i < numCommandLists; i++) { + auto commandList = CommandList::fromHandle(commandLists[i]); + commandList->destroy(); + } + + fence->destroy(); + commandQueue->destroy(); +} + +} // namespace ult +} // namespace L0