Add command list tests

Signed-off-by: Zbigniew Zdanowicz <zbigniew.zdanowicz@intel.com>
This commit is contained in:
Zbigniew Zdanowicz
2022-05-19 12:06:12 +00:00
committed by Compute-Runtime-Automation
parent 3be31b821b
commit 4be1ca618d
5 changed files with 438 additions and 1 deletions

View File

@@ -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

View File

@@ -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<DeviceFixture>;
TEST(CommandListAppendMemoryRangesBarrier, WhenAppendingMemoryRangesBarrierThenSuccessIsReturned) {
MockCommandList commandList;
uint32_t numRanges = 1;
const size_t pRangeSizes = 1;
const char *ranges[pRangeSizes];
const void **pRanges = reinterpret_cast<const void **>(&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<const void **>(&ranges[0]);
auto commandList = new CommandListCoreFamily<gfxCoreFamily>();
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<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
ASSERT_NE(cmdList.end(), itorPC);
auto cmd = genCmdCast<PIPE_CONTROL *>(*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<const void **>(&ranges[0]);
auto commandList = new CommandListCoreFamily<gfxCoreFamily>();
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<ContextImp>(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<uint32_t>(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<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
ASSERT_FALSE(itor.empty());
ASSERT_LT(1, static_cast<int>(itor.size()));
delete event;
delete eventPool;
commandList->destroy();
}
} // namespace ult
} // namespace L0

View File

@@ -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 <vector>
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<void *> 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<uint64_t>(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<uint8_t *>(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

View File

@@ -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()

View File

@@ -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<DeviceFixture>;
HWTEST2_F(CommandQueueExecuteCommandListsSimpleTest, GivenSynchronousModeWhenExecutingCommandListThenSynchronizeIsCalled, IsAtLeastSkl) {
ze_command_queue_desc_t desc;
desc.mode = ZE_COMMAND_QUEUE_MODE_SYNCHRONOUS;
auto mockCmdQ = new MockCommandQueueHw<gfxCoreFamily>(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<gfxCoreFamily>(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<gfxCoreFamily>(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<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
size_t pipeControlsPostSyncNumber = 0u;
for (size_t i = 0; i < pipeControls.size(); i++) {
auto pipeControl = reinterpret_cast<PIPE_CONTROL *>(*pipeControls[i]);
if (pipeControl->getPostSyncOperation() == POST_SYNC_OPERATION::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA) {
EXPECT_EQ(commandQueue->getCsr()->getTagAllocation()->getGpuAddress(), NEO::UnitTestHelper<FamilyType>::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