mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-25 21:42:53 +08:00
Reorganization directory structure [4/n]
Change-Id: Ib868ed62d12ea8f9f123644219ba299e86a658ac
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
add_subdirectories()
|
||||
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_COMMAND_CONTAINER_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/command_container_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/command_encoder_tests.cpp
|
||||
)
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_COMMAND_CONTAINER_TESTS ${NEO_CORE_COMMAND_CONTAINER_TESTS})
|
||||
add_subdirectories()
|
||||
@@ -1,393 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_container/cmdcontainer.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_graphics_allocation.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class CommandContainerTest : public DeviceFixture,
|
||||
public ::testing::Test {
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
::testing::Test::SetUp();
|
||||
DeviceFixture::SetUp();
|
||||
}
|
||||
void TearDown() override {
|
||||
DeviceFixture::TearDown();
|
||||
::testing::Test::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
struct CommandContainerHeapStateTests : public ::testing::Test {
|
||||
class MyMockCommandContainer : public CommandContainer {
|
||||
public:
|
||||
using CommandContainer::dirtyHeaps;
|
||||
};
|
||||
|
||||
MyMockCommandContainer myCommandContainer;
|
||||
};
|
||||
|
||||
TEST_F(CommandContainerHeapStateTests, givenDirtyHeapsWhenSettingStateForAllThenValuesAreCorrect) {
|
||||
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), myCommandContainer.dirtyHeaps);
|
||||
EXPECT_TRUE(myCommandContainer.isAnyHeapDirty());
|
||||
|
||||
myCommandContainer.setDirtyStateForAllHeaps(false);
|
||||
EXPECT_EQ(0u, myCommandContainer.dirtyHeaps);
|
||||
EXPECT_FALSE(myCommandContainer.isAnyHeapDirty());
|
||||
|
||||
for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
|
||||
HeapType heapType = static_cast<HeapType>(i);
|
||||
EXPECT_FALSE(myCommandContainer.isHeapDirty(heapType));
|
||||
}
|
||||
|
||||
myCommandContainer.setDirtyStateForAllHeaps(true);
|
||||
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), myCommandContainer.dirtyHeaps);
|
||||
|
||||
for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
|
||||
HeapType heapType = static_cast<HeapType>(i);
|
||||
EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerHeapStateTests, givenDirtyHeapsWhenSettingStateForSingleHeapThenValuesAreCorrect) {
|
||||
myCommandContainer.dirtyHeaps = 0;
|
||||
EXPECT_FALSE(myCommandContainer.isAnyHeapDirty());
|
||||
|
||||
uint32_t controlVariable = 0;
|
||||
for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
|
||||
HeapType heapType = static_cast<HeapType>(i);
|
||||
|
||||
EXPECT_FALSE(myCommandContainer.isHeapDirty(heapType));
|
||||
myCommandContainer.setHeapDirty(heapType);
|
||||
EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
|
||||
EXPECT_TRUE(myCommandContainer.isAnyHeapDirty());
|
||||
|
||||
controlVariable |= (1 << i);
|
||||
EXPECT_EQ(controlVariable, myCommandContainer.dirtyHeaps);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
|
||||
HeapType heapType = static_cast<HeapType>(i);
|
||||
EXPECT_TRUE(myCommandContainer.isHeapDirty(heapType));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCmdContainerWhenAllocatingHeapsThenSetCorrectAllocationTypes) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
|
||||
for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
|
||||
HeapType heapType = static_cast<HeapType>(i);
|
||||
auto heap = cmdContainer.getIndirectHeap(heapType);
|
||||
|
||||
if (HeapType::INDIRECT_OBJECT == heapType) {
|
||||
EXPECT_EQ(GraphicsAllocation::AllocationType::INTERNAL_HEAP, heap->getGraphicsAllocation()->getAllocationType());
|
||||
EXPECT_NE(0u, heap->getHeapGpuStartOffset());
|
||||
} else {
|
||||
EXPECT_EQ(GraphicsAllocation::AllocationType::LINEAR_STREAM, heap->getGraphicsAllocation()->getAllocationType());
|
||||
EXPECT_EQ(0u, heap->getHeapGpuStartOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCommandContainerWhenInitializeThenEverythingIsInitialized) {
|
||||
CommandContainer cmdContainer;
|
||||
auto status = cmdContainer.initialize(pDevice);
|
||||
EXPECT_TRUE(status);
|
||||
|
||||
EXPECT_EQ(pDevice, cmdContainer.getDevice());
|
||||
EXPECT_NE(cmdContainer.getHeapHelper(), nullptr);
|
||||
EXPECT_EQ(cmdContainer.getCmdBufferAllocations().size(), 1u);
|
||||
EXPECT_NE(cmdContainer.getCommandStream(), nullptr);
|
||||
|
||||
for (uint32_t i = 0; i < HeapType::NUM_TYPES; i++) {
|
||||
auto indirectHeap = cmdContainer.getIndirectHeap(static_cast<HeapType>(i));
|
||||
auto heapAllocation = cmdContainer.getIndirectHeapAllocation(static_cast<HeapType>(i));
|
||||
EXPECT_EQ(indirectHeap->getGraphicsAllocation(), heapAllocation);
|
||||
}
|
||||
EXPECT_EQ(cmdContainer.getInstructionHeapBaseAddress(), pDevice->getMemoryManager()->getInternalHeapBaseAddress(0));
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCommandContainerWhenInitializeWithoutDeviceThenReturnedFalse) {
|
||||
CommandContainer cmdContainer;
|
||||
auto status = cmdContainer.initialize(nullptr);
|
||||
EXPECT_FALSE(status);
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCommandContainerWhenSettingIndirectHeapAllocationThenAllocationIsSet) {
|
||||
CommandContainer cmdContainer;
|
||||
MockGraphicsAllocation mockAllocation;
|
||||
auto heapType = HeapType::DYNAMIC_STATE;
|
||||
cmdContainer.setIndirectHeapAllocation(heapType, &mockAllocation);
|
||||
EXPECT_EQ(cmdContainer.getIndirectHeapAllocation(heapType), &mockAllocation);
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenHeapAllocationsWhenDestroyCommandContainerThenHeapAllocationsAreReused) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
auto heapAllocationsAddress = cmdContainer->getIndirectHeapAllocation(HeapType::DYNAMIC_STATE)->getUnderlyingBuffer();
|
||||
cmdContainer.reset(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
bool status = false;
|
||||
for (uint32_t i = 0; i < HeapType::NUM_TYPES && !status; i++) {
|
||||
status = cmdContainer->getIndirectHeapAllocation(static_cast<HeapType>(i))->getUnderlyingBuffer() == heapAllocationsAddress;
|
||||
}
|
||||
EXPECT_TRUE(status);
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCommandContainerWhenResetTheanStreamsAreNotUsed) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
LinearStream stream;
|
||||
uint32_t usedSize = 1;
|
||||
cmdContainer.getCommandStream()->getSpace(usedSize);
|
||||
EXPECT_EQ(usedSize, cmdContainer.getCommandStream()->getUsed());
|
||||
cmdContainer.reset();
|
||||
EXPECT_NE(usedSize, cmdContainer.getCommandStream()->getUsed());
|
||||
EXPECT_EQ(0u, cmdContainer.getCommandStream()->getUsed());
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCommandContainerWhenWantToAddNullPtrToResidencyContainerThenNothingIsAdded) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
auto size = cmdContainer.getResidencyContainer().size();
|
||||
cmdContainer.addToResidencyContainer(nullptr);
|
||||
EXPECT_EQ(cmdContainer.getResidencyContainer().size(), size);
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCommandContainerWhenWantToAddAleradyAddedAllocationThenNothingIsAdded) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
MockGraphicsAllocation mockAllocation;
|
||||
|
||||
auto sizeBefore = cmdContainer.getResidencyContainer().size();
|
||||
|
||||
cmdContainer.addToResidencyContainer(&mockAllocation);
|
||||
auto sizeAfterFirstAdd = cmdContainer.getResidencyContainer().size();
|
||||
|
||||
EXPECT_NE(sizeBefore, sizeAfterFirstAdd);
|
||||
|
||||
cmdContainer.addToResidencyContainer(&mockAllocation);
|
||||
auto sizeAfterSecondAdd = cmdContainer.getResidencyContainer().size();
|
||||
|
||||
EXPECT_EQ(sizeAfterFirstAdd, sizeAfterSecondAdd);
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenExistingAllocationIsReturned) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
cmdContainer->setDirtyStateForAllHeaps(false);
|
||||
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::SURFACE_STATE);
|
||||
auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
|
||||
|
||||
const size_t sizeRequested = 32;
|
||||
const size_t alignment = 32;
|
||||
|
||||
EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
|
||||
|
||||
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, sizeRequested, alignment);
|
||||
auto newAllocation = heapRequested->getGraphicsAllocation();
|
||||
|
||||
EXPECT_EQ(heap, heapRequested);
|
||||
EXPECT_EQ(heapAllocation, newAllocation);
|
||||
|
||||
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
|
||||
EXPECT_FALSE(cmdContainer->isHeapDirty(HeapType::SURFACE_STATE));
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenUnalignedAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsCorrectlyAligned) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
cmdContainer->setDirtyStateForAllHeaps(false);
|
||||
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::SURFACE_STATE);
|
||||
auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
|
||||
|
||||
const size_t sizeRequested = 32;
|
||||
const size_t alignment = 32;
|
||||
|
||||
heap->getSpace(sizeRequested / 2);
|
||||
|
||||
EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
|
||||
|
||||
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, sizeRequested, alignment);
|
||||
auto newAllocation = heapRequested->getGraphicsAllocation();
|
||||
|
||||
EXPECT_EQ(heap, heapRequested);
|
||||
EXPECT_EQ(heapAllocation, newAllocation);
|
||||
|
||||
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
|
||||
EXPECT_FALSE(cmdContainer->isHeapDirty(HeapType::SURFACE_STATE));
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenNoAlignmentAndAvailableSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenHeapReturnedIsNotAligned) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
cmdContainer->setDirtyStateForAllHeaps(false);
|
||||
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::SURFACE_STATE);
|
||||
auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
|
||||
|
||||
const size_t sizeRequested = 32;
|
||||
const size_t alignment = 0;
|
||||
|
||||
heap->getSpace(sizeRequested / 2);
|
||||
|
||||
EXPECT_GE(heap->getAvailableSpace(), sizeRequested + alignment);
|
||||
|
||||
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, sizeRequested, alignment);
|
||||
auto newAllocation = heapRequested->getGraphicsAllocation();
|
||||
|
||||
EXPECT_EQ(heap, heapRequested);
|
||||
EXPECT_EQ(heapAllocation, newAllocation);
|
||||
|
||||
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (sizeRequested / 2)) == sizeRequested / 2);
|
||||
EXPECT_FALSE(cmdContainer->isHeapDirty(HeapType::SURFACE_STATE));
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenNotEnoughSpaceWhenGetHeapWithRequiredSizeAndAlignmentCalledThenNewAllocationIsReturned) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
cmdContainer->setDirtyStateForAllHeaps(false);
|
||||
auto heapAllocation = cmdContainer->getIndirectHeapAllocation(HeapType::SURFACE_STATE);
|
||||
auto heap = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
|
||||
|
||||
const size_t sizeRequested = 32;
|
||||
const size_t alignment = 32;
|
||||
size_t availableSize = heap->getAvailableSpace();
|
||||
|
||||
heap->getSpace(availableSize - sizeRequested / 2);
|
||||
|
||||
EXPECT_LT(heap->getAvailableSpace(), sizeRequested + alignment);
|
||||
|
||||
auto heapRequested = cmdContainer->getHeapWithRequiredSizeAndAlignment(HeapType::SURFACE_STATE, sizeRequested, alignment);
|
||||
auto newAllocation = heapRequested->getGraphicsAllocation();
|
||||
|
||||
EXPECT_EQ(heap, heapRequested);
|
||||
EXPECT_NE(heapAllocation, newAllocation);
|
||||
|
||||
EXPECT_TRUE((reinterpret_cast<size_t>(heapRequested->getSpace(0)) & (alignment - 1)) == 0);
|
||||
EXPECT_TRUE(cmdContainer->isHeapDirty(HeapType::SURFACE_STATE));
|
||||
|
||||
for (auto deallocation : cmdContainer->getDeallocationContainer()) {
|
||||
cmdContainer->getDevice()->getMemoryManager()->freeGraphicsMemory(deallocation);
|
||||
}
|
||||
cmdContainer->getDeallocationContainer().clear();
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, whenAllocateNextCmdBufferIsCalledThenNewAllocationIsCreatedAndCommandStreamReplaced) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
auto stream = cmdContainer->getCommandStream();
|
||||
ASSERT_NE(nullptr, stream);
|
||||
|
||||
auto initialBuffer = stream->getSpace(0);
|
||||
EXPECT_NE(nullptr, initialBuffer);
|
||||
|
||||
cmdContainer->allocateNextCommandBuffer();
|
||||
|
||||
auto nextBuffer = stream->getSpace(0);
|
||||
auto sizeUsed = stream->getUsed();
|
||||
auto availableSize = stream->getMaxAvailableSpace();
|
||||
|
||||
EXPECT_NE(nullptr, nextBuffer);
|
||||
EXPECT_EQ(0u, sizeUsed);
|
||||
EXPECT_NE(initialBuffer, nextBuffer);
|
||||
const size_t cmdBufSize = CommandContainer::defaultListCmdBufferSize;
|
||||
EXPECT_EQ(cmdBufSize, availableSize);
|
||||
|
||||
ASSERT_EQ(2u, cmdContainer->getCmdBufferAllocations().size());
|
||||
EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[1], cmdContainer->getCommandStream()->getGraphicsAllocation());
|
||||
|
||||
EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[1], cmdContainer->getResidencyContainer().back());
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, whenResettingCommandContainerThenStoredCmdBuffersAreFreedAndStreamIsReplacedWithInitialBuffer) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer);
|
||||
cmdContainer->initialize(pDevice);
|
||||
|
||||
cmdContainer->allocateNextCommandBuffer();
|
||||
cmdContainer->allocateNextCommandBuffer();
|
||||
|
||||
EXPECT_EQ(3u, cmdContainer->getCmdBufferAllocations().size());
|
||||
|
||||
cmdContainer->reset();
|
||||
|
||||
ASSERT_EQ(1u, cmdContainer->getCmdBufferAllocations().size());
|
||||
|
||||
auto stream = cmdContainer->getCommandStream();
|
||||
ASSERT_NE(nullptr, stream);
|
||||
|
||||
auto buffer = stream->getSpace(0);
|
||||
const size_t cmdBufSize = CommandContainer::defaultListCmdBufferSize;
|
||||
|
||||
EXPECT_EQ(cmdContainer->getCmdBufferAllocations()[0]->getUnderlyingBuffer(), buffer);
|
||||
EXPECT_EQ(cmdBufSize, stream->getMaxAvailableSpace());
|
||||
}
|
||||
|
||||
class CommandContainerHeaps : public DeviceFixture,
|
||||
public ::testing::TestWithParam<IndirectHeap::Type> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
DeviceFixture::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
Device,
|
||||
CommandContainerHeaps,
|
||||
testing::Values(
|
||||
IndirectHeap::DYNAMIC_STATE,
|
||||
IndirectHeap::INDIRECT_OBJECT,
|
||||
IndirectHeap::SURFACE_STATE));
|
||||
|
||||
TEST_P(CommandContainerHeaps, givenCommandContainerWhenGetAllowHeapGrowCalledThenHeapIsReturned) {
|
||||
HeapType heap = GetParam();
|
||||
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
auto usedSpaceBefore = cmdContainer.getIndirectHeap(heap)->getUsed();
|
||||
size_t size = 5000;
|
||||
void *ptr = cmdContainer.getHeapSpaceAllowGrow(heap, size);
|
||||
ASSERT_NE(nullptr, ptr);
|
||||
|
||||
auto usedSpaceAfter = cmdContainer.getIndirectHeap(heap)->getUsed();
|
||||
ASSERT_EQ(usedSpaceBefore + size, usedSpaceAfter);
|
||||
}
|
||||
|
||||
TEST_P(CommandContainerHeaps, givenCommandContainerWhenGetingMoreThanAvailableSizeThenBiggerHeapIsReturned) {
|
||||
HeapType heap = GetParam();
|
||||
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
auto usedSpaceBefore = cmdContainer.getIndirectHeap(heap)->getUsed();
|
||||
auto availableSizeBefore = cmdContainer.getIndirectHeap(heap)->getAvailableSpace();
|
||||
|
||||
void *ptr = cmdContainer.getHeapSpaceAllowGrow(heap, availableSizeBefore + 1);
|
||||
ASSERT_NE(nullptr, ptr);
|
||||
|
||||
auto usedSpaceAfter = cmdContainer.getIndirectHeap(heap)->getUsed();
|
||||
auto availableSizeAfter = cmdContainer.getIndirectHeap(heap)->getAvailableSpace();
|
||||
EXPECT_GT(usedSpaceAfter + availableSizeAfter, usedSpaceBefore + availableSizeBefore);
|
||||
}
|
||||
|
||||
TEST_F(CommandContainerTest, givenCommandContainerWhenDestructionThenNonHeapAllocationAreNotDestroyed) {
|
||||
std::unique_ptr<CommandContainer> cmdContainer(new CommandContainer());
|
||||
MockGraphicsAllocation alloc;
|
||||
size_t size = 0x1000;
|
||||
alloc.setSize(size);
|
||||
cmdContainer->initialize(pDevice);
|
||||
cmdContainer->getDeallocationContainer().push_back(&alloc);
|
||||
cmdContainer.reset();
|
||||
EXPECT_EQ(alloc.getUnderlyingBufferSize(), size);
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_container/command_encoder.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class CommandEncoderTests : public DeviceFixture,
|
||||
public ::testing::Test {
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
::testing::Test::SetUp();
|
||||
DeviceFixture::SetUp();
|
||||
}
|
||||
void TearDown() override {
|
||||
DeviceFixture::TearDown();
|
||||
::testing::Test::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
HWTEST_F(CommandEncoderTests, givenImmDataWriteWhenProgrammingMiFlushDwThenSetAllRequiredFields) {
|
||||
using MI_FLUSH_DW = typename FamilyType::MI_FLUSH_DW;
|
||||
uint8_t buffer[2 * sizeof(MI_FLUSH_DW)] = {};
|
||||
LinearStream linearStream(buffer, sizeof(buffer));
|
||||
|
||||
uint64_t gpuAddress = 0x1230000;
|
||||
uint64_t immData = 456;
|
||||
|
||||
EncodeMiFlushDW<FamilyType>::programMiFlushDw(linearStream, gpuAddress, immData);
|
||||
auto miFlushDwCmd = reinterpret_cast<MI_FLUSH_DW *>(buffer);
|
||||
|
||||
EXPECT_EQ(sizeof(MI_FLUSH_DW), linearStream.getUsed());
|
||||
EXPECT_EQ(MI_FLUSH_DW::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA_QWORD, miFlushDwCmd->getPostSyncOperation());
|
||||
EXPECT_EQ(gpuAddress, miFlushDwCmd->getDestinationAddress());
|
||||
EXPECT_EQ(immData, miFlushDwCmd->getImmediateData());
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_COMPILER_INTERFACE_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_cache_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_options_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_interface_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/intermediate_representations_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/linker_mock.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/linker_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_COMPILER_INTERFACE_TESTS ${NEO_CORE_COMPILER_INTERFACE_TESTS})
|
||||
@@ -1,370 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/compiler_interface/compiler_cache.h"
|
||||
#include "shared/source/compiler_interface/compiler_interface.h"
|
||||
#include "shared/source/helpers/aligned_memory.h"
|
||||
#include "shared/source/helpers/hash.h"
|
||||
#include "shared/source/helpers/hw_info.h"
|
||||
#include "shared/source/helpers/string.h"
|
||||
#include "opencl/source/compiler_interface/default_cl_cache_config.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/global_environment.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_context.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_program.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
using namespace NEO;
|
||||
using namespace std;
|
||||
|
||||
class CompilerCacheMock : public CompilerCache {
|
||||
public:
|
||||
CompilerCacheMock() : CompilerCache(CompilerCacheConfig{}) {
|
||||
}
|
||||
|
||||
bool cacheBinary(const std::string kernelFileHash, const char *pBinary, uint32_t binarySize) override {
|
||||
cacheInvoked++;
|
||||
return cacheResult;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> loadCachedBinary(const std::string kernelFileHash, size_t &cachedBinarySize) override {
|
||||
return loadResult ? std::unique_ptr<char[]>{new char[1]} : nullptr;
|
||||
}
|
||||
|
||||
bool cacheResult = false;
|
||||
uint32_t cacheInvoked = 0u;
|
||||
bool loadResult = false;
|
||||
};
|
||||
|
||||
TEST(HashGeneration, givenMisalignedBufferWhenPassedToUpdateFunctionThenProperPtrDataIsUsed) {
|
||||
Hash hash;
|
||||
auto originalPtr = alignedMalloc(1024, MemoryConstants::pageSize);
|
||||
|
||||
memset(originalPtr, 0xFF, 1024);
|
||||
char *misalignedPtr = (char *)originalPtr;
|
||||
misalignedPtr++;
|
||||
|
||||
//values really used
|
||||
misalignedPtr[0] = 1;
|
||||
misalignedPtr[1] = 2;
|
||||
misalignedPtr[2] = 3;
|
||||
misalignedPtr[3] = 4;
|
||||
misalignedPtr[4] = 5;
|
||||
//values not used should be ommitted
|
||||
misalignedPtr[5] = 6;
|
||||
misalignedPtr[6] = 7;
|
||||
|
||||
hash.update(misalignedPtr, 3);
|
||||
auto hash1 = hash.finish();
|
||||
|
||||
hash.reset();
|
||||
hash.update(misalignedPtr, 4);
|
||||
auto hash2 = hash.finish();
|
||||
|
||||
hash.reset();
|
||||
hash.update(misalignedPtr, 5);
|
||||
auto hash3 = hash.finish();
|
||||
|
||||
hash.reset();
|
||||
hash.update(misalignedPtr, 6);
|
||||
auto hash4 = hash.finish();
|
||||
|
||||
EXPECT_NE(hash1, hash2);
|
||||
EXPECT_NE(hash1, hash3);
|
||||
EXPECT_NE(hash1, hash4);
|
||||
EXPECT_NE(hash2, hash3);
|
||||
EXPECT_NE(hash2, hash4);
|
||||
EXPECT_NE(hash3, hash4);
|
||||
|
||||
auto value2 = hash.getValue(misalignedPtr, 0);
|
||||
EXPECT_EQ(0u, value2);
|
||||
|
||||
alignedFree(originalPtr);
|
||||
}
|
||||
|
||||
TEST(HashGeneration, givenMisalignedBufferWithSizeOneWhenPassedToUpdateFunctionThenProperPtrDataIsUsed) {
|
||||
Hash hash;
|
||||
auto originalPtr = alignedMalloc(1024, MemoryConstants::pageSize);
|
||||
|
||||
memset(originalPtr, 0xFF, 1024);
|
||||
char *misalignedPtr = (char *)originalPtr;
|
||||
misalignedPtr++;
|
||||
|
||||
//values really used
|
||||
misalignedPtr[0] = 1;
|
||||
//values not used should be ommitted
|
||||
misalignedPtr[1] = 2;
|
||||
misalignedPtr[2] = 3;
|
||||
misalignedPtr[3] = 4;
|
||||
misalignedPtr[4] = 5;
|
||||
misalignedPtr[5] = 6;
|
||||
misalignedPtr[6] = 7;
|
||||
|
||||
hash.update(misalignedPtr, 1);
|
||||
|
||||
auto value = hash.finish();
|
||||
EXPECT_EQ(0x088350e6600f29c2u, value);
|
||||
|
||||
alignedFree(originalPtr);
|
||||
}
|
||||
|
||||
TEST(CompilerCacheHashTests, WhenHashingThenResultIsDeterministic) {
|
||||
Hash hash;
|
||||
|
||||
std::list<uint64_t> hashes;
|
||||
char data[4] = "aBc";
|
||||
|
||||
for (size_t i = 0; i <= strlen(data); i++) {
|
||||
hash.reset();
|
||||
hash.update(data, i);
|
||||
auto res = hash.finish();
|
||||
|
||||
for (auto &in : hashes) {
|
||||
EXPECT_NE(in, res) << "failed: " << i << " bytes";
|
||||
}
|
||||
hashes.push_back(res);
|
||||
|
||||
// hash once again to make sure results are the same
|
||||
hash.reset();
|
||||
hash.update(data, i);
|
||||
auto res2 = hash.finish();
|
||||
EXPECT_EQ(res, res2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CompilerCacheHashTests, GivenCompilingOptionsWhenGettingCacheThenCorrectCacheIsReturned) {
|
||||
static const size_t bufSize = 64;
|
||||
HardwareInfo hwInfo;
|
||||
|
||||
std::set<std::string> hashes;
|
||||
|
||||
PLATFORM p1 = {(PRODUCT_FAMILY)1};
|
||||
PLATFORM p2 = {(PRODUCT_FAMILY)2};
|
||||
const PLATFORM *platforms[] = {&p1, &p2};
|
||||
FeatureTable s1;
|
||||
FeatureTable s2;
|
||||
s1.ftrSVM = true;
|
||||
s2.ftrSVM = false;
|
||||
const FeatureTable *skus[] = {&s1, &s2};
|
||||
WorkaroundTable w1;
|
||||
WorkaroundTable w2;
|
||||
w1.waDoNotUseMIReportPerfCount = true;
|
||||
w2.waDoNotUseMIReportPerfCount = false;
|
||||
const WorkaroundTable *was[] = {&w1, &w2};
|
||||
|
||||
std::array<std::string, 4> inputArray = {{std::string(""),
|
||||
std::string("12345678901234567890123456789012"),
|
||||
std::string("12345678910234567890123456789012"),
|
||||
std::string("12345678901234567891023456789012")}};
|
||||
|
||||
std::array<std::string, 3> optionsArray = {{std::string(""),
|
||||
std::string("--some --options"),
|
||||
std::string("--some --different --options")}};
|
||||
|
||||
std::array<std::string, 3> internalOptionsArray = {{std::string(""),
|
||||
std::string("--some --options"),
|
||||
std::string("--some --different --options")}};
|
||||
|
||||
std::unique_ptr<char> buf1(new char[bufSize]);
|
||||
std::unique_ptr<char> buf2(new char[bufSize]);
|
||||
std::unique_ptr<char> buf3(new char[bufSize]);
|
||||
std::unique_ptr<char> buf4(new char[bufSize]);
|
||||
|
||||
ArrayRef<char> src;
|
||||
ArrayRef<char> apiOptions;
|
||||
ArrayRef<char> internalOptions;
|
||||
|
||||
for (auto platform : platforms) {
|
||||
hwInfo.platform = *platform;
|
||||
|
||||
for (auto sku : skus) {
|
||||
hwInfo.featureTable = *sku;
|
||||
|
||||
for (auto wa : was) {
|
||||
hwInfo.workaroundTable = *wa;
|
||||
|
||||
for (size_t i1 = 0; i1 < inputArray.size(); i1++) {
|
||||
strcpy_s(buf1.get(), bufSize, inputArray[i1].c_str());
|
||||
src = ArrayRef<char>(buf1.get(), strlen(buf1.get()));
|
||||
for (size_t i2 = 0; i2 < optionsArray.size(); i2++) {
|
||||
strcpy_s(buf2.get(), bufSize, optionsArray[i2].c_str());
|
||||
apiOptions = ArrayRef<char>(buf2.get(), strlen(buf2.get()));
|
||||
for (size_t i3 = 0; i3 < internalOptionsArray.size(); i3++) {
|
||||
strcpy_s(buf3.get(), bufSize, internalOptionsArray[i3].c_str());
|
||||
internalOptions = ArrayRef<char>(buf3.get(), strlen(buf3.get()));
|
||||
|
||||
string hash = CompilerCache::getCachedFileName(hwInfo, src, apiOptions, internalOptions);
|
||||
|
||||
if (hashes.find(hash) != hashes.end()) {
|
||||
FAIL() << "failed: " << i1 << ":" << i2 << ":" << i3;
|
||||
}
|
||||
hashes.emplace(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string hash = CompilerCache::getCachedFileName(hwInfo, src, apiOptions, internalOptions);
|
||||
string hash2 = CompilerCache::getCachedFileName(hwInfo, src, apiOptions, internalOptions);
|
||||
EXPECT_STREQ(hash.c_str(), hash2.c_str());
|
||||
}
|
||||
|
||||
TEST(CompilerCacheTests, GivenEmptyBinaryWhenCachingThenBinaryIsNotCached) {
|
||||
CompilerCache cache(CompilerCacheConfig{});
|
||||
bool ret = cache.cacheBinary("some_hash", nullptr, 12u);
|
||||
EXPECT_FALSE(ret);
|
||||
|
||||
const char *tmp1 = "Data";
|
||||
ret = cache.cacheBinary("some_hash", tmp1, 0u);
|
||||
EXPECT_FALSE(ret);
|
||||
}
|
||||
|
||||
TEST(CompilerCacheTests, GivenNonExistantConfigWhenLoadingFromCacheThenNullIsReturned) {
|
||||
CompilerCache cache(CompilerCacheConfig{});
|
||||
size_t size;
|
||||
auto ret = cache.loadCachedBinary("----do-not-exists----", size);
|
||||
EXPECT_EQ(nullptr, ret);
|
||||
EXPECT_EQ(0U, size);
|
||||
}
|
||||
|
||||
TEST(CompilerCacheTests, GivenExistingConfigWhenLoadingFromCacheThenBinaryIsLoaded) {
|
||||
CompilerCache cache(getDefaultClCompilerCacheConfig());
|
||||
static const char *hash = "SOME_HASH";
|
||||
std::unique_ptr<char> data(new char[32]);
|
||||
for (size_t i = 0; i < 32; i++)
|
||||
data.get()[i] = static_cast<char>(i);
|
||||
|
||||
bool ret = cache.cacheBinary(hash, static_cast<const char *>(data.get()), 32);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
size_t size;
|
||||
auto loadedBin = cache.loadCachedBinary(hash, size);
|
||||
EXPECT_NE(nullptr, loadedBin);
|
||||
EXPECT_NE(0U, size);
|
||||
}
|
||||
|
||||
TEST(CompilerInterfaceCachedTests, GivenNoCachedBinaryWhenBuildingThenErrorIsReturned) {
|
||||
TranslationInput inputArgs{IGC::CodeType::oclC, IGC::CodeType::oclGenBin};
|
||||
|
||||
auto src = "#include \"header.h\"\n__kernel k() {}";
|
||||
|
||||
inputArgs.src = ArrayRef<const char>(src, strlen(src));
|
||||
|
||||
MockCompilerDebugVars fclDebugVars;
|
||||
fclDebugVars.fileName = gEnvironment->fclGetMockFile();
|
||||
gEnvironment->fclPushDebugVars(fclDebugVars);
|
||||
|
||||
MockCompilerDebugVars igcDebugVars;
|
||||
igcDebugVars.fileName = gEnvironment->igcGetMockFile();
|
||||
igcDebugVars.forceBuildFailure = true;
|
||||
gEnvironment->igcPushDebugVars(igcDebugVars);
|
||||
|
||||
std::unique_ptr<CompilerCacheMock> cache(new CompilerCacheMock());
|
||||
auto compilerInterface = std::unique_ptr<CompilerInterface>(CompilerInterface::createInstance(std::move(cache), true));
|
||||
|
||||
TranslationOutput translationOutput;
|
||||
inputArgs.allowCaching = true;
|
||||
MockDevice device;
|
||||
auto err = compilerInterface->build(device, inputArgs, translationOutput);
|
||||
EXPECT_EQ(TranslationOutput::ErrorCode::BuildFailure, err);
|
||||
|
||||
gEnvironment->fclPopDebugVars();
|
||||
gEnvironment->igcPopDebugVars();
|
||||
}
|
||||
|
||||
TEST(CompilerInterfaceCachedTests, GivenCachedBinaryWhenBuildingThenSuccessIsReturned) {
|
||||
TranslationInput inputArgs{IGC::CodeType::oclC, IGC::CodeType::oclGenBin};
|
||||
|
||||
auto src = "#include \"header.h\"\n__kernel k() {}";
|
||||
inputArgs.src = ArrayRef<const char>(src, strlen(src));
|
||||
|
||||
MockCompilerDebugVars fclDebugVars;
|
||||
fclDebugVars.fileName = gEnvironment->fclGetMockFile();
|
||||
gEnvironment->fclPushDebugVars(fclDebugVars);
|
||||
|
||||
MockCompilerDebugVars igcDebugVars;
|
||||
igcDebugVars.fileName = gEnvironment->igcGetMockFile();
|
||||
igcDebugVars.forceBuildFailure = true;
|
||||
gEnvironment->igcPushDebugVars(igcDebugVars);
|
||||
|
||||
std::unique_ptr<CompilerCacheMock> cache(new CompilerCacheMock());
|
||||
cache->loadResult = true;
|
||||
auto compilerInterface = std::unique_ptr<CompilerInterface>(CompilerInterface::createInstance(std::move(cache), true));
|
||||
|
||||
TranslationOutput translationOutput;
|
||||
inputArgs.allowCaching = true;
|
||||
MockDevice device;
|
||||
auto err = compilerInterface->build(device, inputArgs, translationOutput);
|
||||
EXPECT_EQ(TranslationOutput::ErrorCode::Success, err);
|
||||
|
||||
gEnvironment->fclPopDebugVars();
|
||||
gEnvironment->igcPopDebugVars();
|
||||
}
|
||||
|
||||
TEST(CompilerInterfaceCachedTests, givenKernelWithoutIncludesAndBinaryInCacheWhenCompilationRequestedThenFCLIsNotCalled) {
|
||||
MockClDevice device{new MockDevice};
|
||||
MockContext context(&device, true);
|
||||
MockProgram program(*device.getExecutionEnvironment(), &context, false, nullptr);
|
||||
TranslationInput inputArgs{IGC::CodeType::oclC, IGC::CodeType::oclGenBin};
|
||||
|
||||
auto src = "__kernel k() {}";
|
||||
inputArgs.src = ArrayRef<const char>(src, strlen(src));
|
||||
|
||||
// we force both compilers to fail compilation request
|
||||
// at the end we expect CL_SUCCESS which means compilation ends in cache
|
||||
MockCompilerDebugVars fclDebugVars;
|
||||
fclDebugVars.fileName = gEnvironment->fclGetMockFile();
|
||||
fclDebugVars.forceBuildFailure = true;
|
||||
gEnvironment->fclPushDebugVars(fclDebugVars);
|
||||
|
||||
MockCompilerDebugVars igcDebugVars;
|
||||
igcDebugVars.fileName = gEnvironment->igcGetMockFile();
|
||||
igcDebugVars.forceBuildFailure = true;
|
||||
gEnvironment->igcPushDebugVars(igcDebugVars);
|
||||
|
||||
std::unique_ptr<CompilerCacheMock> cache(new CompilerCacheMock());
|
||||
cache->loadResult = true;
|
||||
auto compilerInterface = std::unique_ptr<CompilerInterface>(CompilerInterface::createInstance(std::move(cache), true));
|
||||
TranslationOutput translationOutput;
|
||||
inputArgs.allowCaching = true;
|
||||
auto retVal = compilerInterface->build(device.getDevice(), inputArgs, translationOutput);
|
||||
EXPECT_EQ(TranslationOutput::ErrorCode::Success, retVal);
|
||||
|
||||
gEnvironment->fclPopDebugVars();
|
||||
gEnvironment->igcPopDebugVars();
|
||||
}
|
||||
|
||||
TEST(CompilerInterfaceCachedTests, givenKernelWithIncludesAndBinaryInCacheWhenCompilationRequestedThenFCLIsCalled) {
|
||||
MockClDevice device{new MockDevice};
|
||||
MockContext context(&device, true);
|
||||
MockProgram program(*device.getExecutionEnvironment(), &context, false, nullptr);
|
||||
TranslationInput inputArgs{IGC::CodeType::oclC, IGC::CodeType::oclGenBin};
|
||||
|
||||
auto src = "#include \"file.h\"\n__kernel k() {}";
|
||||
inputArgs.src = ArrayRef<const char>(src, strlen(src));
|
||||
|
||||
MockCompilerDebugVars fclDebugVars;
|
||||
fclDebugVars.fileName = gEnvironment->fclGetMockFile();
|
||||
fclDebugVars.forceBuildFailure = true;
|
||||
gEnvironment->fclPushDebugVars(fclDebugVars);
|
||||
|
||||
std::unique_ptr<CompilerCacheMock> cache(new CompilerCacheMock());
|
||||
cache->loadResult = true;
|
||||
auto compilerInterface = std::unique_ptr<CompilerInterface>(CompilerInterface::createInstance(std::move(cache), true));
|
||||
TranslationOutput translationOutput;
|
||||
inputArgs.allowCaching = true;
|
||||
auto retVal = compilerInterface->build(device.getDevice(), inputArgs, translationOutput);
|
||||
EXPECT_EQ(TranslationOutput::ErrorCode::BuildFailure, retVal);
|
||||
|
||||
gEnvironment->fclPopDebugVars();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "compiler_options.h"
|
||||
|
||||
TEST(CompilerOptions, WhenConcatenationLengthIsCalledThenReturnsSumOfLengthsAndSeperators) {
|
||||
using namespace NEO::CompilerOptions;
|
||||
constexpr auto concatenatedLength = concatenationLength(NEO::CompilerOptions::optDisable);
|
||||
static_assert(optDisable.length() == concatenatedLength, "");
|
||||
static_assert(optDisable.length() + 1 + gtpinRera.length() == concatenationLength(optDisable, gtpinRera), "");
|
||||
static_assert(optDisable.length() + 1 + gtpinRera.length() + 1 + finiteMathOnly.length() == concatenationLength(optDisable, gtpinRera, finiteMathOnly), "");
|
||||
}
|
||||
|
||||
TEST(CompilerOptions, WhenConcatenateIsCalledThenUsesSpaceAsSeparator) {
|
||||
using namespace NEO::CompilerOptions;
|
||||
auto concatenated = concatenate(NEO::CompilerOptions::optDisable, NEO::CompilerOptions::finiteMathOnly);
|
||||
auto expected = (std::string(NEO::CompilerOptions::optDisable) + " " + NEO::CompilerOptions::finiteMathOnly.data());
|
||||
EXPECT_STREQ(expected.c_str(), concatenated.c_str());
|
||||
|
||||
constexpr ConstStringRef toConcatenate[] = {"a", "b", "c"};
|
||||
constexpr ConstConcatenation<concatenationLength(toConcatenate)> constConcatenationSpecificSize(toConcatenate);
|
||||
constexpr ConstConcatenation<> constConcatenationDefaultSize(toConcatenate);
|
||||
EXPECT_TRUE(ConstStringRef("a b c") == constConcatenationSpecificSize);
|
||||
EXPECT_TRUE(ConstStringRef("a b c") == constConcatenationDefaultSize);
|
||||
}
|
||||
|
||||
TEST(CompilerOptions, WhenConcatenateAppendIsCalledThenAddsSpaceAsSeparatorOnlyIfMissing) {
|
||||
using namespace NEO::CompilerOptions;
|
||||
std::string concatenated = NEO::CompilerOptions::optDisable.data();
|
||||
concatenateAppend(concatenated, NEO::CompilerOptions::finiteMathOnly);
|
||||
auto expected = (std::string(NEO::CompilerOptions::optDisable) + " " + NEO::CompilerOptions::finiteMathOnly.data());
|
||||
EXPECT_STREQ(expected.c_str(), concatenated.c_str());
|
||||
concatenated += " ";
|
||||
concatenateAppend(concatenated, NEO::CompilerOptions::fastRelaxedMath);
|
||||
expected += " ";
|
||||
expected += NEO::CompilerOptions::fastRelaxedMath;
|
||||
EXPECT_STREQ(expected.c_str(), concatenated.c_str());
|
||||
}
|
||||
|
||||
TEST(CompilerOptions, WhenCheckingForPresenceOfOptionThenRejectsSubstrings) {
|
||||
EXPECT_FALSE(NEO::CompilerOptions::contains("aaa", "a"));
|
||||
EXPECT_FALSE(NEO::CompilerOptions::contains("aaa", "aa"));
|
||||
EXPECT_TRUE(NEO::CompilerOptions::contains("aaa", "aaa"));
|
||||
EXPECT_FALSE(NEO::CompilerOptions::contains("aaa", "aaaa"));
|
||||
EXPECT_TRUE(NEO::CompilerOptions::contains("aaaa aaa", "aaaa"));
|
||||
EXPECT_TRUE(NEO::CompilerOptions::contains("aa aaaa", "aaaa"));
|
||||
}
|
||||
|
||||
TEST(CompilerOptions, WhenTokenizingThenSpaceIsUsedAsSeparator) {
|
||||
auto tokenizedEmpty = NEO::CompilerOptions::tokenize("");
|
||||
EXPECT_TRUE(tokenizedEmpty.empty());
|
||||
|
||||
auto tokenizedOne = NEO::CompilerOptions::tokenize("abc");
|
||||
ASSERT_EQ(1U, tokenizedOne.size());
|
||||
EXPECT_EQ("abc", tokenizedOne[0]);
|
||||
|
||||
auto tokenizedOneSkipSpaces = NEO::CompilerOptions::tokenize(" abc ");
|
||||
ASSERT_EQ(1U, tokenizedOneSkipSpaces.size());
|
||||
EXPECT_EQ("abc", tokenizedOneSkipSpaces[0]);
|
||||
|
||||
auto tokenizedMultiple = NEO::CompilerOptions::tokenize(" -optA -optB c ");
|
||||
ASSERT_EQ(3U, tokenizedMultiple.size());
|
||||
EXPECT_EQ("-optA", tokenizedMultiple[0]);
|
||||
EXPECT_EQ("-optB", tokenizedMultiple[1]);
|
||||
EXPECT_EQ("c", tokenizedMultiple[2]);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/compiler_interface/intermediate_representations.h"
|
||||
#include "test.h"
|
||||
|
||||
TEST(HasSameMagic, WhenMagicIsMatchedThenReturnTrue) {
|
||||
EXPECT_TRUE(NEO::hasSameMagic("abcd", ArrayRef<const char>("abcdefg").toArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(HasSameMagic, WhenBinaryIsNullptrThenReturnFalse) {
|
||||
EXPECT_FALSE(NEO::hasSameMagic("abcd", {}));
|
||||
}
|
||||
|
||||
TEST(HasSameMagic, WhenBinaryIsShorterThanExpectedMagicThenReturnFalse) {
|
||||
EXPECT_FALSE(NEO::hasSameMagic("abcd", ArrayRef<const char>("ab").toArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(HasSameMagic, WhenMagicIsNotMatchedThenReturnFalse) {
|
||||
EXPECT_FALSE(NEO::hasSameMagic("abcd", ArrayRef<const char>("abcefg").toArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
static constexpr uint8_t llvmBinary[] = "BC\xc0\xde ";
|
||||
|
||||
TEST(IsLlvmBitcode, WhenLlvmMagicWasFoundThenBinaryIsValidLLvm) {
|
||||
EXPECT_TRUE(NEO::isLlvmBitcode(llvmBinary));
|
||||
}
|
||||
|
||||
TEST(IsLlvmBitcode, WhenBinaryIsNullptrThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(IsLlvmBitcode, WhenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>(llvmBinary, 2)));
|
||||
}
|
||||
|
||||
TEST(IsLlvmBitcode, WhenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
const uint8_t notLlvmBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(notLlvmBinary));
|
||||
}
|
||||
|
||||
static constexpr uint32_t spirv[16] = {0x03022307};
|
||||
static constexpr uint32_t spirvInvEndianes[16] = {0x07230203};
|
||||
|
||||
TEST(IsSpirVBitcode, WhenSpirvMagicWasFoundThenBinaryIsValidSpirv) {
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirv), sizeof(spirv))));
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), sizeof(spirvInvEndianes))));
|
||||
}
|
||||
|
||||
TEST(IsSpirVBitcode, WhenBinaryIsNullptrThenBinaryIsNotValidSpirv) {
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(IsSpirVBitcode, WhenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidSpirv) {
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), 2)));
|
||||
}
|
||||
|
||||
TEST(IsSpirVBitcode, WhenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidSpirv) {
|
||||
const uint8_t notSpirvBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(notSpirvBinary));
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/compiler_interface/linker.h"
|
||||
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
|
||||
template <class BaseClass>
|
||||
struct WhiteBox;
|
||||
|
||||
template <class BaseClass>
|
||||
struct Mock;
|
||||
|
||||
template <>
|
||||
struct WhiteBox<NEO::LinkerInput> : NEO::LinkerInput {
|
||||
using BaseClass = NEO::LinkerInput;
|
||||
|
||||
using BaseClass::dataRelocations;
|
||||
using BaseClass::exportedFunctionsSegmentId;
|
||||
using BaseClass::relocations;
|
||||
using BaseClass::symbols;
|
||||
using BaseClass::traits;
|
||||
using BaseClass::valid;
|
||||
};
|
||||
|
||||
template <typename MockT, typename ReturnT, typename... ArgsT>
|
||||
struct LightMockConfig {
|
||||
using MockReturnT = ReturnT;
|
||||
using OverrideT = std::function<ReturnT(MockT *, ArgsT...)>;
|
||||
|
||||
uint32_t timesCalled = 0U;
|
||||
OverrideT overrideFunc;
|
||||
};
|
||||
|
||||
template <typename ConfigT, typename ObjT, typename... ArgsT>
|
||||
typename ConfigT::MockReturnT invokeMocked(ConfigT &config, ObjT obj, ArgsT &&... args) {
|
||||
config.timesCalled += 1;
|
||||
if (config.overrideFunc) {
|
||||
return config.overrideFunc(obj, std::forward<ArgsT>(args)...);
|
||||
} else {
|
||||
return config.originalFunc(obj, std::forward<ArgsT>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
#define LIGHT_MOCK_OVERRIDE_2(NAME, MOCK_T, BASE_T, RETURN_T, ARG0_T, ARG1_T) \
|
||||
struct : LightMockConfig<MOCK_T, RETURN_T, ARG0_T, ARG1_T> { \
|
||||
OverrideT originalFunc = +[](BaseT *obj, ARG0_T arg0, ARG1_T arg1) -> RETURN_T { \
|
||||
return obj->BaseT::NAME(std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1)); \
|
||||
}; \
|
||||
} NAME##MockConfig; \
|
||||
\
|
||||
RETURN_T NAME(ARG0_T arg0, ARG1_T arg1) override { \
|
||||
return invokeMocked(NAME##MockConfig, this, std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1)); \
|
||||
}
|
||||
|
||||
#define LIGHT_MOCK_OVERRIDE_3(NAME, MOCK_T, BASE_T, RETURN_T, ARG0_T, ARG1_T, ARG2_T) \
|
||||
struct : LightMockConfig<MOCK_T, RETURN_T, ARG0_T, ARG1_T, ARG2_T> { \
|
||||
OverrideT originalFunc = +[](BaseT *obj, ARG0_T arg0, ARG1_T arg1, ARG2_T arg2) -> RETURN_T { \
|
||||
return obj->BaseT::NAME(std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1), std::forward<ARG2_T>(arg2)); \
|
||||
}; \
|
||||
} NAME##MockConfig; \
|
||||
\
|
||||
RETURN_T NAME(ARG0_T arg0, ARG1_T arg1, ARG2_T arg2) override { \
|
||||
return invokeMocked(NAME##MockConfig, this, std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1), std::forward<ARG2_T>(arg2)); \
|
||||
}
|
||||
|
||||
template <>
|
||||
struct Mock<NEO::LinkerInput> : WhiteBox<NEO::LinkerInput> {
|
||||
using ThisT = Mock<NEO::LinkerInput>;
|
||||
using BaseT = NEO::LinkerInput;
|
||||
using WhiteBoxBaseT = WhiteBox<BaseT>;
|
||||
|
||||
LIGHT_MOCK_OVERRIDE_2(decodeGlobalVariablesSymbolTable, ThisT, BaseT, bool, const void *, uint32_t);
|
||||
LIGHT_MOCK_OVERRIDE_3(decodeExportedFunctionsSymbolTable, ThisT, BaseT, bool, const void *, uint32_t, uint32_t);
|
||||
LIGHT_MOCK_OVERRIDE_3(decodeRelocationTable, ThisT, BaseT, bool, const void *, uint32_t, uint32_t);
|
||||
};
|
||||
@@ -1,988 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
|
||||
#include "RelocationInfo.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "linker_mock.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
TEST(SegmentTypeTests, givenSegmentTypeWhenAsStringIsCalledThenProperRepresentationIsReturned) {
|
||||
EXPECT_STREQ("UNKOWN", NEO::asString(NEO::SegmentType::Unknown));
|
||||
EXPECT_STREQ("GLOBAL_CONSTANTS", NEO::asString(NEO::SegmentType::GlobalConstants));
|
||||
EXPECT_STREQ("GLOBAL_VARIABLES", NEO::asString(NEO::SegmentType::GlobalVariables));
|
||||
EXPECT_STREQ("INSTRUCTIONS", NEO::asString(NEO::SegmentType::Instructions));
|
||||
}
|
||||
|
||||
TEST(LinkerInputTraitsTests, whenPointerSizeNotSizeThenDefaultsToHostPointerSize) {
|
||||
using PointerSize = NEO::LinkerInput::Traits::PointerSize;
|
||||
auto expectedPointerSize = (sizeof(void *) == 4) ? PointerSize::Ptr32bit : PointerSize::Ptr64bit;
|
||||
auto pointerSize = NEO::LinkerInput::Traits{}.pointerSize;
|
||||
EXPECT_EQ(expectedPointerSize, pointerSize);
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, givenGlobalsSymbolTableThenProperlyDecodesGlobalVariablesAndGlobalConstants) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
vISA::GenSymEntry entry[2] = {{}, {}};
|
||||
entry[0].s_name[0] = 'A';
|
||||
entry[0].s_offset = 8;
|
||||
entry[0].s_size = 16;
|
||||
entry[0].s_type = vISA::GenSymType::S_GLOBAL_VAR;
|
||||
|
||||
entry[1].s_name[0] = 'B';
|
||||
entry[1].s_offset = 24;
|
||||
entry[1].s_size = 8;
|
||||
entry[1].s_type = vISA::GenSymType::S_GLOBAL_VAR_CONST;
|
||||
|
||||
EXPECT_EQ(0U, linkerInput.getSymbols().size());
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalVariables);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalConstants);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsFunctions);
|
||||
|
||||
auto decodeResult = linkerInput.decodeGlobalVariablesSymbolTable(entry, 2);
|
||||
EXPECT_TRUE(decodeResult);
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
|
||||
EXPECT_EQ(2U, linkerInput.getSymbols().size());
|
||||
EXPECT_TRUE(linkerInput.getTraits().exportsGlobalVariables);
|
||||
EXPECT_TRUE(linkerInput.getTraits().exportsGlobalConstants);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsFunctions);
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfInstructionSegments);
|
||||
|
||||
auto symbolA = linkerInput.getSymbols().find("A");
|
||||
ASSERT_NE(linkerInput.getSymbols().end(), symbolA);
|
||||
EXPECT_EQ(entry[0].s_offset, symbolA->second.offset);
|
||||
EXPECT_EQ(entry[0].s_size, symbolA->second.size);
|
||||
EXPECT_EQ(NEO::SegmentType::GlobalVariables, symbolA->second.segment);
|
||||
|
||||
auto symbolB = linkerInput.getSymbols().find("B");
|
||||
ASSERT_NE(linkerInput.getSymbols().end(), symbolB);
|
||||
EXPECT_EQ(entry[1].s_offset, symbolB->second.offset);
|
||||
EXPECT_EQ(entry[1].s_size, symbolB->second.size);
|
||||
EXPECT_EQ(NEO::SegmentType::GlobalConstants, symbolB->second.segment);
|
||||
|
||||
auto symbolC = linkerInput.getSymbols().find("C");
|
||||
EXPECT_EQ(linkerInput.getSymbols().end(), symbolC);
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, givenFunctionsSymbolTableThenProperlyDecodesGlobalVariablesAndGlobalConstants) {
|
||||
// Note : this is subject to change in IGC shotly.
|
||||
// GLOBAL_VAR/CONST will be ultimately allowed only in globalVariables symbol table.
|
||||
NEO::LinkerInput linkerInput;
|
||||
vISA::GenSymEntry entry[2] = {{}, {}};
|
||||
entry[0].s_name[0] = 'A';
|
||||
entry[0].s_offset = 8;
|
||||
entry[0].s_size = 16;
|
||||
entry[0].s_type = vISA::GenSymType::S_GLOBAL_VAR;
|
||||
|
||||
entry[1].s_name[0] = 'B';
|
||||
entry[1].s_offset = 24;
|
||||
entry[1].s_size = 8;
|
||||
entry[1].s_type = vISA::GenSymType::S_GLOBAL_VAR_CONST;
|
||||
|
||||
EXPECT_EQ(0U, linkerInput.getSymbols().size());
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalVariables);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalConstants);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsFunctions);
|
||||
|
||||
auto decodeResult = linkerInput.decodeExportedFunctionsSymbolTable(entry, 2, 3);
|
||||
EXPECT_TRUE(decodeResult);
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
|
||||
EXPECT_EQ(2U, linkerInput.getSymbols().size());
|
||||
EXPECT_TRUE(linkerInput.getTraits().exportsGlobalVariables);
|
||||
EXPECT_TRUE(linkerInput.getTraits().exportsGlobalConstants);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsFunctions);
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfInstructionSegments);
|
||||
|
||||
auto symbolA = linkerInput.getSymbols().find("A");
|
||||
ASSERT_NE(linkerInput.getSymbols().end(), symbolA);
|
||||
EXPECT_EQ(entry[0].s_offset, symbolA->second.offset);
|
||||
EXPECT_EQ(entry[0].s_size, symbolA->second.size);
|
||||
EXPECT_EQ(NEO::SegmentType::GlobalVariables, symbolA->second.segment);
|
||||
|
||||
auto symbolB = linkerInput.getSymbols().find("B");
|
||||
ASSERT_NE(linkerInput.getSymbols().end(), symbolB);
|
||||
EXPECT_EQ(entry[1].s_offset, symbolB->second.offset);
|
||||
EXPECT_EQ(entry[1].s_size, symbolB->second.size);
|
||||
EXPECT_EQ(NEO::SegmentType::GlobalConstants, symbolB->second.segment);
|
||||
|
||||
auto symbolC = linkerInput.getSymbols().find("C");
|
||||
EXPECT_EQ(linkerInput.getSymbols().end(), symbolC);
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, givenGlobalsSymbolTableThenFunctionExportsAreNotAllowed) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
vISA::GenSymEntry entry = {};
|
||||
entry.s_name[0] = 'A';
|
||||
entry.s_offset = 8;
|
||||
entry.s_size = 16;
|
||||
entry.s_type = vISA::GenSymType::S_FUNC;
|
||||
|
||||
auto decodeResult = linkerInput.decodeGlobalVariablesSymbolTable(&entry, 1);
|
||||
EXPECT_FALSE(decodeResult);
|
||||
EXPECT_FALSE(linkerInput.isValid());
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, givenFunctionsSymbolTableThenProperlyDecodesExportedFunctions) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
vISA::GenSymEntry entry[2] = {{}, {}};
|
||||
entry[0].s_name[0] = 'A';
|
||||
entry[0].s_offset = 8;
|
||||
entry[0].s_size = 16;
|
||||
entry[0].s_type = vISA::GenSymType::S_FUNC;
|
||||
|
||||
entry[1].s_name[0] = 'B';
|
||||
entry[1].s_offset = 24;
|
||||
entry[1].s_size = 8;
|
||||
entry[1].s_type = vISA::GenSymType::S_FUNC;
|
||||
|
||||
EXPECT_EQ(0U, linkerInput.getSymbols().size());
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalVariables);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalConstants);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsFunctions);
|
||||
EXPECT_EQ(-1, linkerInput.getExportedFunctionsSegmentId());
|
||||
|
||||
auto decodeResult = linkerInput.decodeExportedFunctionsSymbolTable(entry, 2, 3);
|
||||
EXPECT_TRUE(decodeResult);
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
|
||||
EXPECT_EQ(2U, linkerInput.getSymbols().size());
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalVariables);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalConstants);
|
||||
EXPECT_TRUE(linkerInput.getTraits().exportsFunctions);
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfInstructionSegments);
|
||||
|
||||
auto symbolA = linkerInput.getSymbols().find("A");
|
||||
ASSERT_NE(linkerInput.getSymbols().end(), symbolA);
|
||||
EXPECT_EQ(entry[0].s_offset, symbolA->second.offset);
|
||||
EXPECT_EQ(entry[0].s_size, symbolA->second.size);
|
||||
EXPECT_EQ(NEO::SegmentType::Instructions, symbolA->second.segment);
|
||||
|
||||
auto symbolB = linkerInput.getSymbols().find("B");
|
||||
ASSERT_NE(linkerInput.getSymbols().end(), symbolB);
|
||||
EXPECT_EQ(entry[1].s_offset, symbolB->second.offset);
|
||||
EXPECT_EQ(entry[1].s_size, symbolB->second.size);
|
||||
EXPECT_EQ(NEO::SegmentType::Instructions, symbolB->second.segment);
|
||||
|
||||
EXPECT_EQ(3, linkerInput.getExportedFunctionsSegmentId());
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, givenFunctionsSymbolTableThenUndefIsNotAllowed) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
vISA::GenSymEntry entry = {};
|
||||
entry.s_name[0] = 'A';
|
||||
entry.s_offset = 8;
|
||||
entry.s_size = 16;
|
||||
entry.s_type = vISA::GenSymType::S_UNDEF;
|
||||
|
||||
auto decodeResult = linkerInput.decodeExportedFunctionsSymbolTable(&entry, 1, 3);
|
||||
EXPECT_FALSE(decodeResult);
|
||||
EXPECT_FALSE(linkerInput.isValid());
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, givenRelocationTableThenRelocationEntriesAreProperlyParsed) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
vISA::GenRelocEntry entry = {};
|
||||
entry.r_symbol[0] = 'A';
|
||||
entry.r_offset = 8;
|
||||
entry.r_type = vISA::GenRelocType::R_SYM_ADDR;
|
||||
|
||||
auto decodeResult = linkerInput.decodeRelocationTable(&entry, 1, 3);
|
||||
EXPECT_TRUE(decodeResult);
|
||||
|
||||
EXPECT_EQ(0U, linkerInput.getSymbols().size());
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalVariables);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalConstants);
|
||||
EXPECT_FALSE(linkerInput.getTraits().exportsFunctions);
|
||||
EXPECT_TRUE(linkerInput.getTraits().requiresPatchingOfInstructionSegments);
|
||||
|
||||
decodeResult = linkerInput.decodeRelocationTable(&entry, 1, 1);
|
||||
EXPECT_TRUE(decodeResult);
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, givenRelocationTableThenNoneAsRelocationTypeIsNotAllowed) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
vISA::GenRelocEntry entry = {};
|
||||
entry.r_symbol[0] = 'A';
|
||||
entry.r_offset = 8;
|
||||
entry.r_type = vISA::GenRelocType::R_NONE;
|
||||
|
||||
auto decodeResult = linkerInput.decodeRelocationTable(&entry, 1, 3);
|
||||
EXPECT_FALSE(decodeResult);
|
||||
EXPECT_FALSE(linkerInput.isValid());
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, whenDataRelocationsAreAddedThenProperTraitsAreSet) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo;
|
||||
relocInfo.offset = 7U;
|
||||
relocInfo.relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocInfo.symbolName = "aaa";
|
||||
relocInfo.symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
linkerInput.addDataRelocationInfo(relocInfo);
|
||||
ASSERT_EQ(1U, linkerInput.getDataRelocations().size());
|
||||
EXPECT_EQ(relocInfo.offset, linkerInput.getDataRelocations()[0].offset);
|
||||
EXPECT_EQ(relocInfo.relocationSegment, linkerInput.getDataRelocations()[0].relocationSegment);
|
||||
EXPECT_EQ(relocInfo.symbolName, linkerInput.getDataRelocations()[0].symbolName);
|
||||
EXPECT_EQ(relocInfo.symbolSegment, linkerInput.getDataRelocations()[0].symbolSegment);
|
||||
EXPECT_EQ(relocInfo.type, linkerInput.getDataRelocations()[0].type);
|
||||
EXPECT_TRUE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
|
||||
linkerInput = {};
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
|
||||
relocInfo.relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocInfo.symbolSegment = NEO::SegmentType::GlobalConstants;
|
||||
linkerInput.addDataRelocationInfo(relocInfo);
|
||||
ASSERT_EQ(1U, linkerInput.getDataRelocations().size());
|
||||
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
|
||||
EXPECT_TRUE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenEmptyLinkerInputThenLinkerOutputIsEmpty) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVar, globalConst, exportedFunc;
|
||||
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
bool linkResult = linker.link(globalVar, globalConst, exportedFunc,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenInvalidLinkerInputThenLinkerFails) {
|
||||
WhiteBox<NEO::LinkerInput> mockLinkerInput;
|
||||
mockLinkerInput.valid = false;
|
||||
NEO::Linker linker(mockLinkerInput);
|
||||
NEO::Linker::SegmentInfo globalVar, globalConst, exportedFunc;
|
||||
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
bool linkResult = linker.link(globalVar, globalConst, exportedFunc,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_FALSE(linkResult);
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenUnresolvedExternalWhenPatchingInstructionsThenLinkerFails) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
vISA::GenRelocEntry entry = {};
|
||||
entry.r_symbol[0] = 'A';
|
||||
entry.r_offset = 8;
|
||||
entry.r_type = vISA::GenRelocType::R_SYM_ADDR;
|
||||
auto decodeResult = linkerInput.decodeRelocationTable(&entry, 1, 0);
|
||||
EXPECT_TRUE(decodeResult);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVar, globalConst, exportedFunc;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
instructionSegment.resize(64);
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
|
||||
bool linkResult = linker.link(globalVar, globalConst, exportedFunc,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_FALSE(linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
ASSERT_EQ(1U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, unresolvedExternals[0].instructionsSegmentId);
|
||||
EXPECT_FALSE(unresolvedExternals[0].internalError);
|
||||
EXPECT_EQ(entry.r_offset, unresolvedExternals[0].unresolvedRelocation.offset);
|
||||
EXPECT_EQ(std::string(entry.r_symbol), std::string(unresolvedExternals[0].unresolvedRelocation.symbolName));
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenValidSymbolsAndRelocationsThenInstructionSegmentsAreProperlyPatched) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
|
||||
vISA::GenSymEntry symGlobalVariable = {};
|
||||
symGlobalVariable.s_name[0] = 'A';
|
||||
symGlobalVariable.s_offset = 4;
|
||||
symGlobalVariable.s_size = 16;
|
||||
symGlobalVariable.s_type = vISA::GenSymType::S_GLOBAL_VAR;
|
||||
bool decodeSymSuccess = linkerInput.decodeGlobalVariablesSymbolTable(&symGlobalVariable, 1);
|
||||
|
||||
vISA::GenSymEntry symGlobalConstant = {};
|
||||
symGlobalConstant.s_name[0] = 'B';
|
||||
symGlobalConstant.s_offset = 20;
|
||||
symGlobalConstant.s_size = 8;
|
||||
symGlobalConstant.s_type = vISA::GenSymType::S_GLOBAL_VAR_CONST;
|
||||
decodeSymSuccess = decodeSymSuccess && linkerInput.decodeGlobalVariablesSymbolTable(&symGlobalConstant, 1);
|
||||
|
||||
vISA::GenSymEntry symExportedFunc = {};
|
||||
symExportedFunc.s_name[0] = 'C';
|
||||
symExportedFunc.s_offset = 16;
|
||||
symExportedFunc.s_size = 32;
|
||||
symExportedFunc.s_type = vISA::GenSymType::S_FUNC;
|
||||
|
||||
decodeSymSuccess = decodeSymSuccess && linkerInput.decodeExportedFunctionsSymbolTable(&symExportedFunc, 1, 0);
|
||||
EXPECT_TRUE(decodeSymSuccess);
|
||||
|
||||
vISA::GenRelocEntry relocA = {};
|
||||
relocA.r_symbol[0] = 'A';
|
||||
relocA.r_offset = 0;
|
||||
relocA.r_type = vISA::GenRelocType::R_SYM_ADDR;
|
||||
|
||||
vISA::GenRelocEntry relocB = {};
|
||||
relocB.r_symbol[0] = 'B';
|
||||
relocB.r_offset = 8;
|
||||
relocB.r_type = vISA::GenRelocType::R_SYM_ADDR;
|
||||
|
||||
vISA::GenRelocEntry relocC = {};
|
||||
relocC.r_symbol[0] = 'C';
|
||||
relocC.r_offset = 16;
|
||||
relocC.r_type = vISA::GenRelocType::R_SYM_ADDR;
|
||||
|
||||
vISA::GenRelocEntry relocCPartHigh = {};
|
||||
relocCPartHigh.r_symbol[0] = 'C';
|
||||
relocCPartHigh.r_offset = 28;
|
||||
relocCPartHigh.r_type = vISA::GenRelocType::R_SYM_ADDR_32_HI;
|
||||
|
||||
vISA::GenRelocEntry relocCPartLow = {};
|
||||
relocCPartLow.r_symbol[0] = 'C';
|
||||
relocCPartLow.r_offset = 36;
|
||||
relocCPartLow.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
|
||||
vISA::GenRelocEntry relocs[] = {relocA, relocB, relocC, relocCPartHigh, relocCPartLow};
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, 5, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
uint32_t initData = 0x77777777;
|
||||
instructionSegment.resize(64, static_cast<char>(initData));
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
|
||||
|
||||
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, unresolvedExternals);
|
||||
EXPECT_TRUE(linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(3U, relocatedSymbols.size());
|
||||
|
||||
ASSERT_EQ(1U, relocatedSymbols.count(symGlobalVariable.s_name));
|
||||
ASSERT_EQ(1U, relocatedSymbols.count(symGlobalConstant.s_name));
|
||||
ASSERT_EQ(1U, relocatedSymbols.count(symGlobalVariable.s_name));
|
||||
|
||||
EXPECT_EQ(relocatedSymbols[symGlobalVariable.s_name].gpuAddress, globalVarSegment.gpuAddress + symGlobalVariable.s_offset);
|
||||
EXPECT_EQ(relocatedSymbols[symGlobalConstant.s_name].gpuAddress, globalConstSegment.gpuAddress + symGlobalConstant.s_offset);
|
||||
EXPECT_EQ(relocatedSymbols[symExportedFunc.s_name].gpuAddress, exportedFuncSegment.gpuAddress + symExportedFunc.s_offset);
|
||||
|
||||
EXPECT_EQ(relocatedSymbols[symGlobalVariable.s_name].gpuAddress, *reinterpret_cast<const uintptr_t *>(instructionSegment.data() + relocA.r_offset));
|
||||
EXPECT_EQ(relocatedSymbols[symGlobalConstant.s_name].gpuAddress, *reinterpret_cast<const uintptr_t *>(instructionSegment.data() + relocB.r_offset));
|
||||
EXPECT_EQ(relocatedSymbols[symExportedFunc.s_name].gpuAddress, *reinterpret_cast<const uintptr_t *>(instructionSegment.data() + relocC.r_offset));
|
||||
|
||||
auto funcGpuAddressAs64bit = static_cast<uint64_t>(relocatedSymbols[symExportedFunc.s_name].gpuAddress);
|
||||
auto funcAddressLow = static_cast<uint32_t>(funcGpuAddressAs64bit & 0xffffffff);
|
||||
auto funcAddressHigh = static_cast<uint32_t>((funcGpuAddressAs64bit >> 32) & 0xffffffff);
|
||||
EXPECT_EQ(funcAddressLow, *reinterpret_cast<const uint32_t *>(instructionSegment.data() + relocCPartLow.r_offset));
|
||||
EXPECT_EQ(initData, *reinterpret_cast<const uint32_t *>(instructionSegment.data() + relocCPartLow.r_offset - sizeof(uint32_t)));
|
||||
EXPECT_EQ(initData, *reinterpret_cast<const uint32_t *>(instructionSegment.data() + relocCPartLow.r_offset + sizeof(uint32_t)));
|
||||
|
||||
EXPECT_EQ(funcAddressHigh, *reinterpret_cast<const uint32_t *>(instructionSegment.data() + relocCPartHigh.r_offset));
|
||||
EXPECT_EQ(initData, *reinterpret_cast<const uint32_t *>(instructionSegment.data() + relocCPartHigh.r_offset - sizeof(uint32_t)));
|
||||
EXPECT_EQ(initData, *reinterpret_cast<const uint32_t *>(instructionSegment.data() + relocCPartHigh.r_offset + sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenInvalidSymbolOffsetWhenPatchingInstructionsThenRelocationFails) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
|
||||
vISA::GenSymEntry symGlobalVariable = {};
|
||||
symGlobalVariable.s_name[0] = 'A';
|
||||
symGlobalVariable.s_offset = 64;
|
||||
symGlobalVariable.s_size = 16;
|
||||
symGlobalVariable.s_type = vISA::GenSymType::S_GLOBAL_VAR;
|
||||
bool decodeSymSuccess = linkerInput.decodeGlobalVariablesSymbolTable(&symGlobalVariable, 1);
|
||||
EXPECT_TRUE(decodeSymSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = symGlobalVariable.s_offset;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
instructionSegment.resize(64, 0);
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
|
||||
|
||||
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_FALSE(linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
|
||||
globalVarSegment.segmentSize = symGlobalVariable.s_offset + symGlobalVariable.s_size;
|
||||
linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, unresolvedExternals);
|
||||
EXPECT_TRUE(linkResult);
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfInstructionsFails) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
|
||||
vISA::GenSymEntry symGlobalVariable = {};
|
||||
symGlobalVariable.s_name[0] = 'A';
|
||||
symGlobalVariable.s_offset = 64;
|
||||
symGlobalVariable.s_size = 16;
|
||||
symGlobalVariable.s_type = vISA::GenSymType::S_GLOBAL_VAR;
|
||||
bool decodeSymSuccess = linkerInput.decodeGlobalVariablesSymbolTable(&symGlobalVariable, 1);
|
||||
EXPECT_TRUE(decodeSymSuccess);
|
||||
|
||||
vISA::GenRelocEntry relocA = {};
|
||||
relocA.r_symbol[0] = 'A';
|
||||
relocA.r_offset = 32;
|
||||
relocA.r_type = vISA::GenRelocType::R_SYM_ADDR;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocA, 1, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = symGlobalVariable.s_offset + symGlobalVariable.s_size;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
instructionSegment.resize(relocA.r_offset + sizeof(uintptr_t), 0);
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = relocA.r_offset;
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
|
||||
|
||||
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_FALSE(linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(1U, relocatedSymbols.size());
|
||||
ASSERT_EQ(1U, unresolvedExternals.size());
|
||||
EXPECT_TRUE(unresolvedExternals[0].internalError);
|
||||
|
||||
patchableInstructionSegments[0].segmentSize = relocA.r_offset + sizeof(uintptr_t);
|
||||
linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_TRUE(linkResult);
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenUnknownSymbolTypeWhenPatchingInstructionsThenRelocationFails) {
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
|
||||
vISA::GenSymEntry symGlobalVariable = {};
|
||||
symGlobalVariable.s_name[0] = 'A';
|
||||
symGlobalVariable.s_offset = 0;
|
||||
symGlobalVariable.s_size = 16;
|
||||
symGlobalVariable.s_type = vISA::GenSymType::S_GLOBAL_VAR;
|
||||
bool decodeSymSuccess = linkerInput.decodeGlobalVariablesSymbolTable(&symGlobalVariable, 1);
|
||||
EXPECT_TRUE(decodeSymSuccess);
|
||||
|
||||
vISA::GenRelocEntry relocA = {};
|
||||
relocA.r_symbol[0] = 'A';
|
||||
relocA.r_offset = 0;
|
||||
relocA.r_type = vISA::GenRelocType::R_SYM_ADDR;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocA, 1, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
instructionSegment.resize(64, 0);
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
|
||||
|
||||
ASSERT_EQ(1U, linkerInput.symbols.count("A"));
|
||||
linkerInput.symbols["A"].segment = NEO::SegmentType::Unknown;
|
||||
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_FALSE(linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
ASSERT_EQ(0U, unresolvedExternals.size());
|
||||
|
||||
linkerInput.symbols["A"].segment = NEO::SegmentType::GlobalVariables;
|
||||
linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
|
||||
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
|
||||
unresolvedExternals);
|
||||
EXPECT_TRUE(linkResult);
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenInvalidSourceSegmentWhenPatchingDataSegmentsThenLinkerFails) {
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
|
||||
NEO::Linker::SegmentInfo emptySegmentInfo;
|
||||
NEO::Linker::PatchableSegment emptyPatchableSegment;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> nonEmptypatchableSegmentData;
|
||||
nonEmptypatchableSegmentData.resize(64, 8U);
|
||||
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
|
||||
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
|
||||
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo;
|
||||
relocInfo.offset = 0U;
|
||||
relocInfo.symbolName = "aaa";
|
||||
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
linkerInput.dataRelocations.push_back(relocInfo);
|
||||
|
||||
{
|
||||
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
|
||||
linkerInput.traits.requiresPatchingOfGlobalConstantsBuffer = false;
|
||||
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::Unknown;
|
||||
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_FALSE(linkResult);
|
||||
EXPECT_EQ(1U, unresolvedExternals.size());
|
||||
|
||||
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
unresolvedExternals.clear();
|
||||
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
}
|
||||
|
||||
{
|
||||
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = false;
|
||||
linkerInput.traits.requiresPatchingOfGlobalConstantsBuffer = true;
|
||||
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::Unknown;
|
||||
unresolvedExternals.clear();
|
||||
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
emptyPatchableSegment, nonEmptypatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_FALSE(linkResult);
|
||||
EXPECT_EQ(1U, unresolvedExternals.size());
|
||||
|
||||
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
unresolvedExternals.clear();
|
||||
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
emptyPatchableSegment, nonEmptypatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenUnknownRelocationSegmentWhenPatchingDataSegmentsThenLinkerFails) {
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
|
||||
NEO::Linker::SegmentInfo emptySegmentInfo;
|
||||
NEO::Linker::PatchableSegment emptyPatchableSegment;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> nonEmptypatchableSegmentData;
|
||||
nonEmptypatchableSegmentData.resize(64, 8U);
|
||||
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
|
||||
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
|
||||
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo;
|
||||
relocInfo.offset = 0U;
|
||||
relocInfo.symbolName = "aaa";
|
||||
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
linkerInput.dataRelocations.push_back(relocInfo);
|
||||
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::Unknown;
|
||||
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
|
||||
|
||||
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_FALSE(linkResult);
|
||||
EXPECT_EQ(1U, unresolvedExternals.size());
|
||||
|
||||
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
unresolvedExternals.clear();
|
||||
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenRelocationTypeWithHighPartOfAddressWhenPatchingDataSegmentsThenLinkerFails) {
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
|
||||
NEO::Linker::SegmentInfo emptySegmentInfo;
|
||||
NEO::Linker::PatchableSegment emptyPatchableSegment;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> nonEmptypatchableSegmentData;
|
||||
nonEmptypatchableSegmentData.resize(64, 8U);
|
||||
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
|
||||
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
|
||||
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo;
|
||||
relocInfo.offset = 0U;
|
||||
relocInfo.symbolName = "aaa";
|
||||
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::AddressHigh;
|
||||
linkerInput.dataRelocations.push_back(relocInfo);
|
||||
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
|
||||
|
||||
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_FALSE(linkResult);
|
||||
EXPECT_EQ(1U, unresolvedExternals.size());
|
||||
|
||||
linkerInput.dataRelocations[0].type = NEO::LinkerInput::RelocationInfo::Type::AddressLow;
|
||||
unresolvedExternals.clear();
|
||||
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenValidSymbolsAndRelocationsThenDataSegmentsAreProperlyPatched) {
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
|
||||
std::vector<char> globalConstantsSegmentData;
|
||||
globalConstantsSegmentData.resize(128, 7U);
|
||||
|
||||
std::vector<char> globalVariablesSegmentData;
|
||||
globalVariablesSegmentData.resize(256, 13U);
|
||||
|
||||
NEO::Linker::SegmentInfo globalConstantsSegmentInfo, globalVariablesSegmentInfo;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
NEO::Linker::PatchableSegment globalConstantsPatchableSegment, globalVariablesPatchableSegment;
|
||||
globalConstantsSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalConstantsSegmentData.data());
|
||||
globalConstantsSegmentInfo.segmentSize = globalConstantsSegmentData.size();
|
||||
globalConstantsPatchableSegment.hostPointer = globalConstantsSegmentData.data();
|
||||
globalConstantsPatchableSegment.segmentSize = globalConstantsSegmentData.size();
|
||||
|
||||
globalVariablesSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalVariablesSegmentData.data());
|
||||
globalVariablesSegmentInfo.segmentSize = globalVariablesSegmentData.size();
|
||||
globalVariablesPatchableSegment.hostPointer = globalVariablesSegmentData.data();
|
||||
globalVariablesPatchableSegment.segmentSize = globalVariablesSegmentData.size();
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocationInfo[5];
|
||||
// GlobalVar -> GlobalVar
|
||||
relocationInfo[0].offset = 8U;
|
||||
relocationInfo[0].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[0].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[0].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalConst -> GlobalVar
|
||||
relocationInfo[1].offset = 24U;
|
||||
relocationInfo[1].relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[1].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[1].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalConst -> GlobalConst
|
||||
relocationInfo[2].offset = 40U;
|
||||
relocationInfo[2].relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[2].symbolSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[2].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalVar -> GlobalConst
|
||||
relocationInfo[3].offset = 56U;
|
||||
relocationInfo[3].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[3].symbolSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[3].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalVar Low -> GlobalVar
|
||||
relocationInfo[4].offset = 72;
|
||||
relocationInfo[4].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[4].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[4].type = NEO::LinkerInput::RelocationInfo::Type::AddressLow;
|
||||
|
||||
uint32_t initValue = 0;
|
||||
for (const auto &reloc : relocationInfo) {
|
||||
linkerInput.addDataRelocationInfo(reloc);
|
||||
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
|
||||
if (reloc.type == NEO::LinkerInput::RelocationInfo::Type::Address) {
|
||||
*reinterpret_cast<uintptr_t *>(ptrOffset(dstRaw, static_cast<size_t>(reloc.offset))) = initValue * 4; // relocations to global data are currently based on patchIncrement, simulate init data
|
||||
} else {
|
||||
*reinterpret_cast<uint32_t *>(ptrOffset(dstRaw, static_cast<size_t>(reloc.offset))) = initValue * 4; // relocations to global data are currently based on patchIncrement, simulate init data
|
||||
}
|
||||
++initValue;
|
||||
}
|
||||
|
||||
auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, {},
|
||||
globalVariablesPatchableSegment, globalConstantsPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(7U, *reinterpret_cast<uint8_t *>(globalConstantsPatchableSegment.hostPointer));
|
||||
EXPECT_EQ(13U, *reinterpret_cast<uint8_t *>(globalVariablesPatchableSegment.hostPointer));
|
||||
|
||||
initValue = 0;
|
||||
for (const auto &reloc : relocationInfo) {
|
||||
void *srcRaw = (reloc.symbolSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
|
||||
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
|
||||
uint8_t *src = reinterpret_cast<uint8_t *>(srcRaw);
|
||||
uint8_t *dst = reinterpret_cast<uint8_t *>(dstRaw);
|
||||
|
||||
// make sure no buffer underflow occured
|
||||
EXPECT_EQ(dst[0], dst[reloc.offset - 1]);
|
||||
|
||||
// check patch-incremented value
|
||||
if (reloc.type == NEO::LinkerInput::RelocationInfo::Type::Address) {
|
||||
// make sure no buffer overflow occured
|
||||
EXPECT_EQ(dst[0], dst[reloc.offset + sizeof(uintptr_t)]);
|
||||
EXPECT_EQ(reinterpret_cast<uintptr_t>(src) + initValue * 4, *reinterpret_cast<uintptr_t *>(dst + reloc.offset)) << initValue;
|
||||
} else {
|
||||
// make sure no buffer overflow occured
|
||||
EXPECT_EQ(dst[0], dst[reloc.offset + sizeof(uint32_t)]);
|
||||
EXPECT_EQ(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(src)) + initValue * 4, *reinterpret_cast<uint32_t *>(dst + reloc.offset)) << initValue;
|
||||
}
|
||||
++initValue;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenValidSymbolsAndRelocationsWhenPatchin32bitBinaryThenDataSegmentsAreProperlyPatchedWithLowerPartOfTheAddress) {
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
linkerInput.setPointerSize(NEO::LinkerInput::Traits::PointerSize::Ptr32bit);
|
||||
NEO::Linker linker(linkerInput);
|
||||
|
||||
std::vector<char> globalConstantsSegmentData;
|
||||
globalConstantsSegmentData.resize(128, 7U);
|
||||
|
||||
std::vector<char> globalVariablesSegmentData;
|
||||
globalVariablesSegmentData.resize(256, 13U);
|
||||
|
||||
NEO::Linker::SegmentInfo globalConstantsSegmentInfo, globalVariablesSegmentInfo;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
NEO::Linker::PatchableSegment globalConstantsPatchableSegment, globalVariablesPatchableSegment;
|
||||
globalConstantsSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalConstantsSegmentData.data());
|
||||
globalConstantsSegmentInfo.segmentSize = globalConstantsSegmentData.size();
|
||||
globalConstantsPatchableSegment.hostPointer = globalConstantsSegmentData.data();
|
||||
globalConstantsPatchableSegment.segmentSize = globalConstantsSegmentData.size();
|
||||
|
||||
globalVariablesSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalVariablesSegmentData.data());
|
||||
globalVariablesSegmentInfo.segmentSize = globalVariablesSegmentData.size();
|
||||
globalVariablesPatchableSegment.hostPointer = globalVariablesSegmentData.data();
|
||||
globalVariablesPatchableSegment.segmentSize = globalVariablesSegmentData.size();
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocationInfo[5];
|
||||
// GlobalVar -> GlobalVar
|
||||
relocationInfo[0].offset = 8U;
|
||||
relocationInfo[0].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[0].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[0].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalConst -> GlobalVar
|
||||
relocationInfo[1].offset = 24U;
|
||||
relocationInfo[1].relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[1].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[1].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalConst -> GlobalConst
|
||||
relocationInfo[2].offset = 40U;
|
||||
relocationInfo[2].relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[2].symbolSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[2].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalVar -> GlobalConst
|
||||
relocationInfo[3].offset = 56U;
|
||||
relocationInfo[3].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[3].symbolSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocationInfo[3].type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
|
||||
// GlobalVar Low -> GlobalVar
|
||||
relocationInfo[4].offset = 72;
|
||||
relocationInfo[4].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[4].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocationInfo[4].type = NEO::LinkerInput::RelocationInfo::Type::AddressLow;
|
||||
|
||||
uint32_t initValue = 0;
|
||||
for (const auto &reloc : relocationInfo) {
|
||||
linkerInput.addDataRelocationInfo(reloc);
|
||||
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
|
||||
*reinterpret_cast<uint32_t *>(ptrOffset(dstRaw, static_cast<size_t>(reloc.offset))) = initValue * 4; // relocations to global data are currently based on patchIncrement, simulate init data
|
||||
++initValue;
|
||||
}
|
||||
|
||||
auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, {},
|
||||
globalVariablesPatchableSegment, globalConstantsPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(7U, *reinterpret_cast<uint8_t *>(globalConstantsPatchableSegment.hostPointer));
|
||||
EXPECT_EQ(13U, *reinterpret_cast<uint8_t *>(globalVariablesPatchableSegment.hostPointer));
|
||||
|
||||
initValue = 0;
|
||||
for (const auto &reloc : relocationInfo) {
|
||||
void *srcRaw = (reloc.symbolSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
|
||||
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
|
||||
uint8_t *src = reinterpret_cast<uint8_t *>(srcRaw);
|
||||
uint8_t *dst = reinterpret_cast<uint8_t *>(dstRaw);
|
||||
|
||||
// make sure no buffer under/overflow occured
|
||||
EXPECT_EQ(dst[0], dst[reloc.offset - 1]);
|
||||
EXPECT_EQ(dst[0], dst[reloc.offset + sizeof(uint32_t)]);
|
||||
|
||||
// check patch-incremented value
|
||||
EXPECT_EQ(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(src)) + initValue * 4, *reinterpret_cast<uint32_t *>(dst + reloc.offset)) << initValue;
|
||||
++initValue;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfDataSegmentsFails) {
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
|
||||
NEO::Linker::SegmentInfo emptySegmentInfo;
|
||||
NEO::Linker::PatchableSegment emptyPatchableSegment;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
|
||||
std::vector<char> nonEmptypatchableSegmentData;
|
||||
nonEmptypatchableSegmentData.resize(64, 8U);
|
||||
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
|
||||
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
|
||||
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo;
|
||||
relocInfo.offset = 64U;
|
||||
relocInfo.symbolName = "aaa";
|
||||
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
linkerInput.dataRelocations.push_back(relocInfo);
|
||||
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
|
||||
|
||||
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_FALSE(linkResult);
|
||||
EXPECT_EQ(1U, unresolvedExternals.size());
|
||||
|
||||
linkerInput.dataRelocations[0].offset = 32;
|
||||
unresolvedExternals.clear();
|
||||
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
|
||||
nonEmptypatchableSegment, emptyPatchableSegment, {},
|
||||
unresolvedExternals);
|
||||
|
||||
EXPECT_TRUE(linkResult);
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
}
|
||||
|
||||
TEST(LinkerErrorMessageTests, whenListOfUnresolvedExternalsIsEmptyThenErrorTypeDefaultsToInternalError) {
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
std::vector<std::string> segmentsNames{"kernel1", "kernel2"};
|
||||
auto err = NEO::constructLinkerErrorMessage(unresolvedExternals, segmentsNames);
|
||||
EXPECT_EQ(std::string("Internal linker error"), err);
|
||||
}
|
||||
|
||||
TEST(LinkerErrorMessageTests, givenListOfUnresolvedExternalsThenSymbolNameOrSymbolSegmentTypeGetsEmbededInErrorMessage) {
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
std::vector<std::string> segmentsNames{"kernel1", "kernel2"};
|
||||
NEO::Linker::UnresolvedExternal unresolvedExternal = {};
|
||||
unresolvedExternal.instructionsSegmentId = 1;
|
||||
unresolvedExternal.internalError = false;
|
||||
unresolvedExternal.unresolvedRelocation.offset = 64;
|
||||
unresolvedExternal.unresolvedRelocation.symbolName = "arrayABC";
|
||||
unresolvedExternal.unresolvedRelocation.relocationSegment = NEO::SegmentType::Instructions;
|
||||
unresolvedExternals.push_back(unresolvedExternal);
|
||||
auto err = NEO::constructLinkerErrorMessage(unresolvedExternals, segmentsNames);
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(unresolvedExternal.unresolvedRelocation.symbolName.c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(segmentsNames[unresolvedExternal.instructionsSegmentId].c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::Not(::testing::HasSubstr("internal error")));
|
||||
|
||||
unresolvedExternals[0].internalError = true;
|
||||
err = NEO::constructLinkerErrorMessage(unresolvedExternals, segmentsNames);
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(unresolvedExternal.unresolvedRelocation.symbolName.c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(segmentsNames[unresolvedExternal.instructionsSegmentId].c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr("internal linker error"));
|
||||
|
||||
err = NEO::constructLinkerErrorMessage(unresolvedExternals, {});
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(unresolvedExternal.unresolvedRelocation.symbolName.c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::Not(::testing::HasSubstr(segmentsNames[unresolvedExternal.instructionsSegmentId].c_str())));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr("internal linker error"));
|
||||
|
||||
unresolvedExternals[0].unresolvedRelocation.relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
err = NEO::constructLinkerErrorMessage(unresolvedExternals, {});
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(NEO::asString(NEO::SegmentType::GlobalConstants)));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
|
||||
|
||||
unresolvedExternals[0].unresolvedRelocation.relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
err = NEO::constructLinkerErrorMessage(unresolvedExternals, {});
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(NEO::asString(NEO::SegmentType::GlobalVariables)));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
|
||||
|
||||
unresolvedExternals[0].unresolvedRelocation.relocationSegment = NEO::SegmentType::Unknown;
|
||||
err = NEO::constructLinkerErrorMessage(unresolvedExternals, {});
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(NEO::asString(NEO::SegmentType::Unknown)));
|
||||
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_DEBUG_SETTINGS_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debug_settings_manager_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debug_settings_manager_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_DEBUG_SETTINGS_TESTS ${NEO_CORE_DEBUG_SETTINGS_TESTS})
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/debug_settings/debug_settings_manager.h"
|
||||
#include "shared/source/helpers/file_io.h"
|
||||
#include "shared/source/utilities/directory.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace NEO;
|
||||
using namespace std;
|
||||
|
||||
#undef DECLARE_DEBUG_VARIABLE
|
||||
|
||||
class TestDebugFlagsChecker {
|
||||
public:
|
||||
static bool isEqual(int32_t returnedValue, bool defaultValue) {
|
||||
if (returnedValue == 0) {
|
||||
return !defaultValue;
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isEqual(int32_t returnedValue, int32_t defaultValue) {
|
||||
return returnedValue == defaultValue;
|
||||
}
|
||||
|
||||
static bool isEqual(string returnedValue, string defaultValue) {
|
||||
return returnedValue == defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
template <DebugFunctionalityLevel DebugLevel>
|
||||
class TestDebugSettingsManager : public DebugSettingsManager<DebugLevel> {
|
||||
public:
|
||||
using DebugSettingsManager<DebugLevel>::dumpFlags;
|
||||
using DebugSettingsManager<DebugLevel>::settingsDumpFileName;
|
||||
|
||||
TestDebugSettingsManager() : DebugSettingsManager<DebugLevel>("") {}
|
||||
SettingsReader *getSettingsReader() {
|
||||
return DebugSettingsManager<DebugLevel>::readerImpl.get();
|
||||
}
|
||||
};
|
||||
|
||||
using FullyEnabledTestDebugManager = TestDebugSettingsManager<DebugFunctionalityLevel::Full>;
|
||||
using FullyDisabledTestDebugManager = TestDebugSettingsManager<DebugFunctionalityLevel::None>;
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/memory_manager/graphics_allocation.h"
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "utilities/base_object_utils.h"
|
||||
#include "shared/source/utilities/debug_file_reader.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "debug_settings_manager_fixture.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
TEST(DebugSettingsManager, WithDebugFunctionality) {
|
||||
FullyEnabledTestDebugManager debugManager;
|
||||
|
||||
EXPECT_FALSE(debugManager.disabled());
|
||||
|
||||
EXPECT_EQ(nullptr, debugManager.injectFcn);
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, WithDebugFunctionalityHasSettingsReader) {
|
||||
FullyEnabledTestDebugManager debugManager;
|
||||
// SettingsReader created
|
||||
EXPECT_NE(nullptr, debugManager.getSettingsReader());
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, WithoutDebugFunctionality) {
|
||||
FullyDisabledTestDebugManager debugManager;
|
||||
|
||||
// Should not be enabled without debug functionality
|
||||
EXPECT_TRUE(debugManager.disabled());
|
||||
// SettingsReader not created
|
||||
EXPECT_EQ(nullptr, debugManager.getSettingsReader());
|
||||
|
||||
// debug variables / flags set to default
|
||||
#define DECLARE_DEBUG_VARIABLE(dataType, variableName, defaultValue, description) \
|
||||
{ \
|
||||
bool isEqual = TestDebugFlagsChecker::isEqual(debugManager.flags.variableName.get(), defaultValue); \
|
||||
EXPECT_TRUE(isEqual); \
|
||||
}
|
||||
#include "debug_variables.inl"
|
||||
#undef DECLARE_DEBUG_VARIABLE
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, whenDebugManagerIsDisabledThenDebugFunctionalityIsNotAvailableAtCompileTime) {
|
||||
TestDebugSettingsManager<DebugFunctionalityLevel::None> debugManager;
|
||||
|
||||
static_assert(debugManager.disabled(), "");
|
||||
static_assert(false == debugManager.registryReadAvailable(), "");
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, whenDebugManagerIsFullyEnabledThenAllDebugFunctionalityIsAvailableAtCompileTime) {
|
||||
TestDebugSettingsManager<DebugFunctionalityLevel::Full> debugManager;
|
||||
|
||||
static_assert(false == debugManager.disabled(), "");
|
||||
static_assert(debugManager.registryReadAvailable(), "");
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, whenOnlyRegKeysAreEnabledThenAllOtherDebugFunctionalityIsNotAvailableAtCompileTime) {
|
||||
TestDebugSettingsManager<DebugFunctionalityLevel::RegKeys> debugManager;
|
||||
|
||||
static_assert(false == debugManager.disabled(), "");
|
||||
static_assert(debugManager.registryReadAvailable(), "");
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, givenTwoPossibleVariantsOfHardwareInfoOverrideStringThenOutputStringIsTheSame) {
|
||||
FullyEnabledTestDebugManager debugManager;
|
||||
std::string hwInfoConfig;
|
||||
|
||||
// Set HardwareInfoOverride as regular string (i.e. as in Windows Registry)
|
||||
std::string str1 = "1x4x8";
|
||||
debugManager.flags.HardwareInfoOverride.set(str1);
|
||||
debugManager.getHardwareInfoOverride(hwInfoConfig);
|
||||
EXPECT_EQ(str1, hwInfoConfig);
|
||||
|
||||
// Set HardwareInfoOverride as quoted string (i.e. as in igdrcl.config file)
|
||||
std::string str2 = "\"1x4x8\"";
|
||||
debugManager.flags.HardwareInfoOverride.set(str2);
|
||||
hwInfoConfig = debugManager.flags.HardwareInfoOverride.get();
|
||||
EXPECT_EQ(str2, hwInfoConfig);
|
||||
debugManager.getHardwareInfoOverride(hwInfoConfig);
|
||||
EXPECT_EQ(str1, hwInfoConfig);
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, givenStringDebugVariableWhenLongValueExeedingSmallStringOptimizationIsAssignedThenMemoryLeakIsNotReported) {
|
||||
DebugManagerStateRestore debugManagerStateRestore;
|
||||
DebugManager.flags.AUBDumpCaptureFileName.set("ThisIsVeryLongStringValueThatExceedSizeSpecifiedBySmallStringOptimizationAndCausesInternalStringBufferResize");
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, givenNullAsReaderImplInDebugManagerWhenSettingReaderImplThenItsSetProperly) {
|
||||
FullyDisabledTestDebugManager debugManager;
|
||||
auto readerImpl = SettingsReader::create("");
|
||||
debugManager.setReaderImpl(readerImpl);
|
||||
EXPECT_EQ(readerImpl, debugManager.getReaderImpl());
|
||||
}
|
||||
TEST(DebugSettingsManager, givenReaderImplInDebugManagerWhenSettingDifferentReaderImplThenItsSetProperly) {
|
||||
FullyDisabledTestDebugManager debugManager;
|
||||
auto readerImpl = SettingsReader::create("");
|
||||
debugManager.setReaderImpl(readerImpl);
|
||||
|
||||
auto readerImpl2 = SettingsReader::create("");
|
||||
debugManager.setReaderImpl(readerImpl2);
|
||||
EXPECT_EQ(readerImpl2, debugManager.getReaderImpl());
|
||||
}
|
||||
|
||||
TEST(DebugSettingsManager, givenPrintDebugSettingsEnabledWhenCallingDumpFlagsThenFlagsAreWrittenToDumpFile) {
|
||||
testing::internal::CaptureStdout();
|
||||
FullyEnabledTestDebugManager debugManager;
|
||||
debugManager.flags.PrintDebugSettings.set(true);
|
||||
debugManager.flags.LoopAtPlatformInitialize.set(true);
|
||||
debugManager.flags.Enable64kbpages.set(1);
|
||||
debugManager.flags.TbxServer.set("192.168.0.1");
|
||||
|
||||
// Clear dump files and generate new
|
||||
std::remove(FullyEnabledTestDebugManager::settingsDumpFileName);
|
||||
debugManager.dumpFlags();
|
||||
|
||||
// Validate allSettingsDumpFile
|
||||
SettingsFileReader allSettingsReader{FullyEnabledTestDebugManager::settingsDumpFileName};
|
||||
#define DECLARE_DEBUG_VARIABLE(dataType, varName, defaultValue, description) \
|
||||
EXPECT_EQ(debugManager.flags.varName.get(), allSettingsReader.getSetting(#varName, defaultValue));
|
||||
|
||||
#include "debug_variables.inl"
|
||||
#undef DECLARE_DEBUG_VARIABLE
|
||||
std::remove(FullyEnabledTestDebugManager::settingsDumpFileName);
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
ASSERT_NE(0u, output.size());
|
||||
|
||||
EXPECT_NE(std::string::npos, output.find("Non-default value of debug variable: TbxServer = 192.168.0.1"));
|
||||
EXPECT_NE(std::string::npos, output.find("Non-default value of debug variable: LoopAtPlatformInitialize = 1"));
|
||||
EXPECT_NE(std::string::npos, output.find("Non-default value of debug variable: PrintDebugSettings = 1"));
|
||||
EXPECT_NE(std::string::npos, output.find("Non-default value of debug variable: Enable64kbpages = 1"));
|
||||
}
|
||||
|
||||
TEST(AllocationInfoLogging, givenBaseGraphicsAllocationWhenGettingImplementationSpecificAllocationInfoThenReturnEmptyInfoString) {
|
||||
GraphicsAllocation graphicsAllocation(0, GraphicsAllocation::AllocationType::UNKNOWN, nullptr, 0ull, 0ull, 0, MemoryPool::MemoryNull);
|
||||
EXPECT_STREQ(graphicsAllocation.getAllocationInfoString().c_str(), "");
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_DEVICE_BINARY_FORMAT_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_decoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_encoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ar_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ocl_elf_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_patchtokens_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_tests.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_validator_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_DEVICE_BINARY_FORMAT_TESTS ${NEO_DEVICE_BINARY_FORMAT_TESTS})
|
||||
@@ -1,426 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/ar/ar_decoder.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO::Ar;
|
||||
|
||||
TEST(ArDecoderIsAr, WhenNotArThenReturnsFalse) {
|
||||
ArrayRef<const uint8_t> empty;
|
||||
EXPECT_FALSE(isAr(empty));
|
||||
|
||||
const uint8_t notAr[] = "aaaaa";
|
||||
EXPECT_FALSE(isAr(notAr));
|
||||
}
|
||||
|
||||
TEST(ArDecoderIsAr, WhenValidArThenReturnsTrue) {
|
||||
auto emptyAr = ArrayRef<const uint8_t>::fromAny(arMagic.begin(), arMagic.size());
|
||||
EXPECT_TRUE(isAr(emptyAr));
|
||||
}
|
||||
|
||||
TEST(ArDecoderReadDecimal, WhenNullOrSpaceIsEncounteredThenParsingStops) {
|
||||
const char spaceDelimited[] = "213 123";
|
||||
const char nullTerminateDelimited[] = {'4', '5', '6', '\0', '7', '8', '9'};
|
||||
EXPECT_EQ(213U, readDecimal<sizeof(spaceDelimited)>(spaceDelimited));
|
||||
EXPECT_EQ(456U, readDecimal<sizeof(nullTerminateDelimited)>(nullTerminateDelimited));
|
||||
}
|
||||
|
||||
TEST(ArDecoderReadDecimal, WhenNullOrSpaceIsNotEncounteredThenParsesTillTheEnd) {
|
||||
const char noteDelimited[] = "213123";
|
||||
EXPECT_EQ(2131U, readDecimal<4>(noteDelimited));
|
||||
}
|
||||
|
||||
TEST(ArDecoderIsStringPadding, GivenCharacterThenReturnsTrueOnlyIfArStringPaddingCharacter) {
|
||||
EXPECT_TRUE(isStringPadding(' '));
|
||||
EXPECT_TRUE(isStringPadding('/'));
|
||||
EXPECT_TRUE(isStringPadding('\0'));
|
||||
EXPECT_FALSE(isStringPadding('\t'));
|
||||
EXPECT_FALSE(isStringPadding('\r'));
|
||||
EXPECT_FALSE(isStringPadding('\n'));
|
||||
EXPECT_FALSE(isStringPadding('0'));
|
||||
EXPECT_FALSE(isStringPadding('a'));
|
||||
}
|
||||
|
||||
TEST(ArDecoderReadUnpaddedString, GivenPaddedStringTheReturnsUnpaddedStringPart) {
|
||||
const char paddedString[] = "abcd/ \0";
|
||||
auto unpadded = readUnpaddedString<sizeof(paddedString)>(paddedString);
|
||||
EXPECT_EQ(paddedString, unpadded.begin());
|
||||
EXPECT_EQ(4U, unpadded.size());
|
||||
}
|
||||
|
||||
TEST(ArDecoderReadUnpaddedString, GivenEmptyPaddedStringTheReturnsEmptyString) {
|
||||
const char paddedString[] = "// \0";
|
||||
auto unpadded = readUnpaddedString<sizeof(paddedString)>(paddedString);
|
||||
EXPECT_TRUE(unpadded.empty());
|
||||
}
|
||||
|
||||
TEST(ArDecoderReadUnpaddedString, GivenUnpaddedStringTheReturnsDataInBounds) {
|
||||
const char paddedString[] = "abcdefgh";
|
||||
auto unpadded = readUnpaddedString<3>(paddedString);
|
||||
EXPECT_EQ(paddedString, unpadded.begin());
|
||||
EXPECT_EQ(3U, unpadded.size());
|
||||
}
|
||||
|
||||
TEST(ArDecoderReadLongFileName, GivenOffsetThenParsesCorrectString) {
|
||||
const char names[] = "abcde/fgh/ij";
|
||||
auto name0 = readLongFileName(names, 0U);
|
||||
auto name1 = readLongFileName(names, 6U);
|
||||
auto name2 = readLongFileName(names, 10U);
|
||||
auto name3 = readLongFileName(names, 40U);
|
||||
EXPECT_EQ(names, name0.begin());
|
||||
EXPECT_EQ(5U, name0.size());
|
||||
|
||||
EXPECT_EQ(names + 6U, name1.begin());
|
||||
EXPECT_EQ(3U, name1.size());
|
||||
|
||||
EXPECT_EQ(names + 10U, name2.begin());
|
||||
EXPECT_EQ(2U, name2.size());
|
||||
|
||||
EXPECT_TRUE(name3.empty());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenNotArThenFailDecoding) {
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr({}, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, ar.magic);
|
||||
EXPECT_EQ(0U, ar.files.size());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Not an AR archive - mismatched file signature", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenValidArThenDecodingSucceeds) {
|
||||
const uint8_t data[8] = "1234567";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = 'a';
|
||||
fileEntry0.identifier[1] = '/';
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data, data + sizeof(data));
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
|
||||
ASSERT_EQ(1U, ar.files.size());
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
|
||||
EXPECT_EQ("a", ar.files[0].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
|
||||
EXPECT_EQ(8U, ar.files[0].fileData.size());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenArWhenFileEntryHeaderHasEmptyIdentifierThenDecodingFails) {
|
||||
const uint8_t data[8] = "1234567";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data, data + sizeof(data));
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, ar.magic);
|
||||
EXPECT_EQ(0U, ar.files.size());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Corrupt AR archive - file entry does not have identifier : '/ '", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenInvalidFileEntryHeaderTrailingMagicThenDecodingSucceedsButWarningIsEmitted) {
|
||||
const uint8_t data[8] = "1234567";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = 'a';
|
||||
fileEntry0.identifier[1] = '/';
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
fileEntry0.trailingMagic[0] = 'a';
|
||||
fileEntry0.trailingMagic[1] = 'a';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data, data + sizeof(data));
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
|
||||
ASSERT_EQ(1U, ar.files.size());
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
|
||||
EXPECT_EQ("a", ar.files[0].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
|
||||
EXPECT_EQ(8U, ar.files[0].fileData.size());
|
||||
|
||||
EXPECT_FALSE(decodeWarnings.empty());
|
||||
EXPECT_STREQ("File entry header with identifier 'a/ ' has invalid header trailing string", decodeWarnings.c_str());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenOutOfBoundsFileEntryDataThenFailDecoding) {
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = 'a';
|
||||
fileEntry0.identifier[1] = '/';
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, ar.magic);
|
||||
EXPECT_EQ(0U, ar.files.size());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Corrupt AR archive - out of bounds data of file entry with idenfitier 'a/ '", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenValidTwoFilesEntriesWith2byteAlignedDataThenDecodingSucceeds) {
|
||||
const uint8_t data0[8] = "1234567";
|
||||
const uint8_t data1[16] = "9ABCDEFGHIJKLMN";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = 'a';
|
||||
fileEntry0.identifier[1] = '/';
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
|
||||
|
||||
ArFileEntryHeader fileEntry1;
|
||||
fileEntry1.identifier[0] = 'b';
|
||||
fileEntry1.identifier[1] = '/';
|
||||
fileEntry1.fileSizeInBytes[0] = '1';
|
||||
fileEntry1.fileSizeInBytes[1] = '6';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry1), reinterpret_cast<const uint8_t *>(&fileEntry1 + 1));
|
||||
arStorage.insert(arStorage.end(), data1, data1 + sizeof(data1));
|
||||
|
||||
ASSERT_EQ(arMagic.size() + 2 * sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(data1), arStorage.size());
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
|
||||
|
||||
ASSERT_EQ(2U, ar.files.size());
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
|
||||
EXPECT_EQ("a", ar.files[0].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
|
||||
EXPECT_EQ(8U, ar.files[0].fileData.size());
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0)), ar.files[1].fullHeader);
|
||||
EXPECT_EQ("b", ar.files[1].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(ArFileEntryHeader), ar.files[1].fileData.begin());
|
||||
EXPECT_EQ(16U, ar.files[1].fileData.size());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenValidTwoFileEntriesWith2byteUnalignedDataAndPaddingThenImplicitPaddingIsTakenIntoAccount) {
|
||||
const uint8_t data0[7] = "123456";
|
||||
const uint8_t data1[15] = "9ABCDEFGHIJKLM";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = 'a';
|
||||
fileEntry0.identifier[1] = '/';
|
||||
fileEntry0.fileSizeInBytes[0] = '7';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
|
||||
arStorage.push_back('\0'); // implicit 2-byte alignment padding
|
||||
|
||||
ArFileEntryHeader fileEntry1;
|
||||
fileEntry1.identifier[0] = 'b';
|
||||
fileEntry1.identifier[1] = '/';
|
||||
fileEntry1.fileSizeInBytes[0] = '1';
|
||||
fileEntry1.fileSizeInBytes[1] = '5';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry1), reinterpret_cast<const uint8_t *>(&fileEntry1 + 1));
|
||||
arStorage.insert(arStorage.end(), data1, data1 + sizeof(data1));
|
||||
arStorage.push_back('\0'); // implicit 2-byte alignment padding
|
||||
ASSERT_EQ(arMagic.size() + 2 * sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(data1) + 2, arStorage.size());
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
|
||||
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
|
||||
|
||||
ASSERT_EQ(2U, ar.files.size());
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
|
||||
EXPECT_EQ("a", ar.files[0].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
|
||||
EXPECT_EQ(7U, ar.files[0].fileData.size());
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0) + 1), ar.files[1].fullHeader);
|
||||
EXPECT_EQ("b", ar.files[1].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0) + 1 + sizeof(ArFileEntryHeader), ar.files[1].fileData.begin());
|
||||
EXPECT_EQ(15U, ar.files[1].fileData.size());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenSpecialFileWithLongFilenamesThenSpecialFileIsProperlyRecognized) {
|
||||
const uint8_t names[8] = "123456/";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ArFileEntryHeader fileEntrySpecial;
|
||||
fileEntrySpecial.identifier[0] = '/';
|
||||
fileEntrySpecial.identifier[1] = '/';
|
||||
fileEntrySpecial.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntrySpecial), reinterpret_cast<const uint8_t *>(&fileEntrySpecial + 1));
|
||||
arStorage.insert(arStorage.end(), names, names + sizeof(names));
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_EQ("//", ar.longFileNamesEntry.fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.longFileNamesEntry.fileData.begin());
|
||||
EXPECT_EQ(8U, ar.longFileNamesEntry.fileData.size());
|
||||
EXPECT_EQ(0U, ar.files.size());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenFilesWithLongFilenamesThenNamesAreProperlyDecoded) {
|
||||
const uint8_t longNames[] = "my_identifier_is_longer_than_16_charters/my_identifier_is_even_longer_than_previous_one/";
|
||||
size_t longNamesLen = sizeof(longNames) - 1U; // 88, ignore nullterminate
|
||||
const uint8_t data0[8] = "1234567";
|
||||
const uint8_t data1[16] = "9ABCDEFGHIJKLMN";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
|
||||
ArFileEntryHeader fileEntrySpecial;
|
||||
fileEntrySpecial.identifier[0] = '/';
|
||||
fileEntrySpecial.identifier[1] = '/';
|
||||
fileEntrySpecial.fileSizeInBytes[0] = '8';
|
||||
fileEntrySpecial.fileSizeInBytes[1] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntrySpecial), reinterpret_cast<const uint8_t *>(&fileEntrySpecial + 1));
|
||||
arStorage.insert(arStorage.end(), longNames, longNames + longNamesLen);
|
||||
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = '/';
|
||||
fileEntry0.identifier[1] = '0';
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
|
||||
|
||||
ArFileEntryHeader fileEntry1;
|
||||
fileEntry1.identifier[0] = '/';
|
||||
fileEntry1.identifier[1] = '4';
|
||||
fileEntry1.identifier[2] = '1';
|
||||
fileEntry1.fileSizeInBytes[0] = '1';
|
||||
fileEntry1.fileSizeInBytes[1] = '6';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry1), reinterpret_cast<const uint8_t *>(&fileEntry1 + 1));
|
||||
arStorage.insert(arStorage.end(), data1, data1 + sizeof(data1));
|
||||
|
||||
ASSERT_EQ(arMagic.size() + 3 * sizeof(ArFileEntryHeader) + longNamesLen + sizeof(data0) + sizeof(data1), arStorage.size());
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_EQ("//", ar.longFileNamesEntry.fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.longFileNamesEntry.fileData.begin());
|
||||
EXPECT_EQ(longNamesLen, ar.longFileNamesEntry.fileData.size());
|
||||
|
||||
ASSERT_EQ(2U, ar.files.size());
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen), ar.files[0].fullHeader);
|
||||
EXPECT_EQ("my_identifier_is_longer_than_16_charters", ar.files[0].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
|
||||
EXPECT_EQ(8U, ar.files[0].fileData.size());
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen + sizeof(ArFileEntryHeader) + sizeof(data0)), ar.files[1].fullHeader);
|
||||
EXPECT_EQ("my_identifier_is_even_longer_than_previous_one", ar.files[1].fileName);
|
||||
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen + sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(ArFileEntryHeader), ar.files[1].fileData.begin());
|
||||
EXPECT_EQ(16U, ar.files[1].fileData.size());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenFilesWithLongFilenamesWhenFileNamesSpecialEntryNotPresentThenDecodingFails) {
|
||||
const uint8_t data0[8] = "1234567";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = '/';
|
||||
fileEntry0.identifier[1] = '0';
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, ar.magic);
|
||||
EXPECT_EQ(0U, ar.files.size());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Corrupt AR archive - long file name entry has broken identifier : '/0 '", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(ArDecoderDecodeAr, GivenFilesWithLongFilenamesWhenLongNameIsOutOfBoundsThenDecodingFails) {
|
||||
const uint8_t longNames[] = "my_identifier_is_longer_than_16_charters/my_identifier_is_even_longer_than_previous_one/";
|
||||
size_t longNamesLen = sizeof(longNames) - 1U; // 88, ignore nullterminate
|
||||
const uint8_t data0[8] = "1234567";
|
||||
std::vector<uint8_t> arStorage;
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
|
||||
ArFileEntryHeader fileEntrySpecial;
|
||||
fileEntrySpecial.identifier[0] = '/';
|
||||
fileEntrySpecial.identifier[1] = '/';
|
||||
fileEntrySpecial.fileSizeInBytes[0] = '8';
|
||||
fileEntrySpecial.fileSizeInBytes[1] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntrySpecial), reinterpret_cast<const uint8_t *>(&fileEntrySpecial + 1));
|
||||
arStorage.insert(arStorage.end(), longNames, longNames + longNamesLen);
|
||||
|
||||
ArFileEntryHeader fileEntry0;
|
||||
fileEntry0.identifier[0] = '/';
|
||||
fileEntry0.identifier[1] = '1';
|
||||
fileEntry0.identifier[2] = '0';
|
||||
fileEntry0.identifier[3] = '0';
|
||||
fileEntry0.fileSizeInBytes[0] = '8';
|
||||
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
|
||||
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, ar.magic);
|
||||
EXPECT_EQ(0U, ar.files.size());
|
||||
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Corrupt AR archive - long file name entry has broken identifier : '/100 '", decodeErrors.c_str());
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/compiler_interface/intermediate_representations.h"
|
||||
#include "shared/source/device_binary_format/ar/ar_encoder.h"
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
#include "shared/source/helpers/string.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace NEO::Ar;
|
||||
|
||||
TEST(ArFileEntryHeader, GivenDefaultArFileEntryHeaderThenSectionAreProperlyPopulated) {
|
||||
ArFileEntryHeader header = {};
|
||||
EXPECT_EQ(ConstStringRef("/ ", 16), ConstStringRef(header.identifier));
|
||||
EXPECT_EQ(ConstStringRef("0 ", 12), ConstStringRef(header.fileModificationTimestamp));
|
||||
EXPECT_EQ(ConstStringRef("0 ", 6), ConstStringRef(header.ownerId));
|
||||
EXPECT_EQ(ConstStringRef("0 ", 6), ConstStringRef(header.groupId));
|
||||
EXPECT_EQ(ConstStringRef("644 ", 8), ConstStringRef(header.fileMode));
|
||||
EXPECT_EQ(ConstStringRef("0 ", 10), ConstStringRef(header.fileSizeInBytes));
|
||||
EXPECT_EQ(ConstStringRef("\x60\x0A", 2), ConstStringRef(header.trailingMagic));
|
||||
}
|
||||
|
||||
TEST(ArEncoder, GivenTooLongIdentifierThenAppendingFileFails) {
|
||||
const uint8_t fileData[] = "2357111317192329";
|
||||
ArEncoder encoder;
|
||||
EXPECT_EQ(nullptr, encoder.appendFileEntry("my_identifier_is_longer_than_16_charters", fileData));
|
||||
}
|
||||
|
||||
TEST(ArEncoder, GivenEmptyIdentifierThenAppendingFileFails) {
|
||||
const uint8_t fileData[] = "2357111317192329";
|
||||
ArEncoder encoder;
|
||||
EXPECT_EQ(nullptr, encoder.appendFileEntry("", fileData));
|
||||
}
|
||||
|
||||
TEST(ArEncoder, GivenEmptyArThenEncodedFileConsistsOfOnlyArMagic) {
|
||||
ArEncoder encoder;
|
||||
auto arData = encoder.encode();
|
||||
EXPECT_EQ(arMagic.size(), arData.size());
|
||||
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
|
||||
}
|
||||
|
||||
TEST(ArEncoder, GivenValidFileEntriesThenAppendingFileSucceeds) {
|
||||
std::string fileName = "file1.txt";
|
||||
const uint8_t fileData[18] = "23571113171923293";
|
||||
ArEncoder encoder;
|
||||
auto returnedSection = encoder.appendFileEntry(fileName, fileData);
|
||||
ASSERT_NE(nullptr, returnedSection);
|
||||
ArFileEntryHeader expectedSection;
|
||||
memcpy_s(expectedSection.identifier, sizeof(expectedSection.identifier), fileName.c_str(), fileName.size());
|
||||
expectedSection.identifier[fileName.size()] = '/';
|
||||
expectedSection.fileSizeInBytes[0] = '1';
|
||||
expectedSection.fileSizeInBytes[1] = '8';
|
||||
EXPECT_EQ(0, memcmp(returnedSection, &expectedSection, sizeof(expectedSection)));
|
||||
|
||||
auto arData = encoder.encode();
|
||||
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
|
||||
ASSERT_EQ(arData.size(), arMagic.size() + sizeof(fileData) + sizeof(ArFileEntryHeader));
|
||||
ArFileEntryHeader *file0 = reinterpret_cast<ArFileEntryHeader *>(arData.data() + arMagic.size());
|
||||
auto file0Data = arData.data() + arMagic.size() + sizeof(ArFileEntryHeader);
|
||||
EXPECT_EQ(0, memcmp(file0, &expectedSection, sizeof(expectedSection)));
|
||||
EXPECT_EQ(0, memcmp(file0Data, fileData, sizeof(fileData)));
|
||||
}
|
||||
|
||||
TEST(ArEncoder, GivenValidTwoFileEntriesWith2byteUnalignedDataThenPaddingIsImplicitlyAdded) {
|
||||
std::string fileName0 = "a";
|
||||
std::string fileName1 = "b";
|
||||
const uint8_t data0[7] = "123456";
|
||||
const uint8_t data1[16] = "9ABCDEFGHIJKLMN";
|
||||
ArEncoder encoder;
|
||||
|
||||
auto returnedSection = encoder.appendFileEntry(fileName0, data0);
|
||||
ASSERT_NE(nullptr, returnedSection);
|
||||
ArFileEntryHeader expectedSection0;
|
||||
expectedSection0.identifier[0] = 'a';
|
||||
expectedSection0.identifier[1] = '/';
|
||||
expectedSection0.fileSizeInBytes[0] = '7';
|
||||
EXPECT_EQ(0, memcmp(returnedSection, &expectedSection0, sizeof(expectedSection0)));
|
||||
|
||||
returnedSection = encoder.appendFileEntry(fileName1, data1);
|
||||
ASSERT_NE(nullptr, returnedSection);
|
||||
ArFileEntryHeader expectedSection1;
|
||||
expectedSection1.identifier[0] = 'b';
|
||||
expectedSection1.identifier[1] = '/';
|
||||
expectedSection1.fileSizeInBytes[0] = '1';
|
||||
expectedSection1.fileSizeInBytes[1] = '6';
|
||||
EXPECT_EQ(0, memcmp(returnedSection, &expectedSection1, sizeof(expectedSection1)));
|
||||
|
||||
auto arData = encoder.encode();
|
||||
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
|
||||
ASSERT_EQ(arData.size(), arMagic.size() + sizeof(data0) + sizeof(data1) + 2 * sizeof(ArFileEntryHeader) + 1);
|
||||
ArFileEntryHeader *file0 = reinterpret_cast<ArFileEntryHeader *>(arData.data() + arMagic.size());
|
||||
auto file0Data = arData.data() + arMagic.size() + sizeof(ArFileEntryHeader);
|
||||
ArFileEntryHeader *file1 = reinterpret_cast<ArFileEntryHeader *>(arData.data() + arMagic.size() + sizeof(data0) + sizeof(ArFileEntryHeader) + 1);
|
||||
auto file1Data = arData.data() + arMagic.size() + sizeof(data0) + 2 * sizeof(ArFileEntryHeader) + 1;
|
||||
EXPECT_EQ(0, memcmp(file0, &expectedSection0, sizeof(expectedSection0)));
|
||||
EXPECT_EQ(0, memcmp(file0Data, data0, sizeof(data0)));
|
||||
EXPECT_EQ(0, memcmp(file1, &expectedSection1, sizeof(expectedSection1)));
|
||||
EXPECT_EQ(0, memcmp(file1Data, data1, sizeof(data1)));
|
||||
}
|
||||
|
||||
TEST(ArEncoder, GivenValidTwoFileEntriesWhen8BytePaddingIsRequestedThenPaddingFileEntriesAreAddedWhenNeeded) {
|
||||
std::string fileName0 = "a";
|
||||
std::string fileName1 = "b";
|
||||
std::string fileName2 = "c";
|
||||
const uint8_t data0[4] = "123"; // will require padding before
|
||||
const uint8_t data1[8] = "9ABCDEF"; // won't require padding before
|
||||
const uint8_t data2[16] = "9ABCDEF"; // will require padding before
|
||||
ArEncoder encoder(true);
|
||||
|
||||
encoder.appendFileEntry(fileName0, data0);
|
||||
encoder.appendFileEntry(fileName1, data1);
|
||||
encoder.appendFileEntry(fileName2, data2);
|
||||
|
||||
auto arData = encoder.encode();
|
||||
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
|
||||
ASSERT_EQ(arData.size(), arMagic.size() + sizeof(data0) + sizeof(data1) + sizeof(data2) + 5 * sizeof(ArFileEntryHeader) + 16);
|
||||
|
||||
auto files = arData.data() + arMagic.size();
|
||||
|
||||
ArFileEntryHeader *pad0 = reinterpret_cast<ArFileEntryHeader *>(files);
|
||||
auto pad0Data = reinterpret_cast<uint8_t *>(pad0) + sizeof(ArFileEntryHeader);
|
||||
|
||||
ArFileEntryHeader *file0 = reinterpret_cast<ArFileEntryHeader *>(pad0Data + 8);
|
||||
auto file0Data = reinterpret_cast<uint8_t *>(file0) + sizeof(ArFileEntryHeader);
|
||||
|
||||
ArFileEntryHeader *file1 = reinterpret_cast<ArFileEntryHeader *>(file0Data + sizeof(data0));
|
||||
auto file1Data = reinterpret_cast<uint8_t *>(file1) + sizeof(ArFileEntryHeader);
|
||||
|
||||
ArFileEntryHeader *pad1 = reinterpret_cast<ArFileEntryHeader *>(file1Data + sizeof(data1));
|
||||
auto pad1Data = reinterpret_cast<uint8_t *>(pad1) + sizeof(ArFileEntryHeader);
|
||||
|
||||
ArFileEntryHeader *file2 = reinterpret_cast<ArFileEntryHeader *>(pad1Data + 8);
|
||||
auto file2Data = reinterpret_cast<uint8_t *>(file2) + sizeof(ArFileEntryHeader);
|
||||
|
||||
EXPECT_EQ(0U, ptrDiff(file0Data, arData.data()) % 8);
|
||||
EXPECT_EQ(0U, ptrDiff(file1Data, arData.data()) % 8);
|
||||
EXPECT_EQ(0U, ptrDiff(file2Data, arData.data()) % 8);
|
||||
|
||||
EXPECT_EQ(0, memcmp(file0Data, data0, sizeof(data0)));
|
||||
EXPECT_EQ(0, memcmp(file1Data, data1, sizeof(data1)));
|
||||
EXPECT_EQ(0, memcmp(file2Data, data2, sizeof(data2)));
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/ar/ar.h"
|
||||
#include "shared/source/device_binary_format/ar/ar_decoder.h"
|
||||
#include "shared/source/device_binary_format/ar/ar_encoder.h"
|
||||
#include "shared/source/device_binary_format/device_binary_formats.h"
|
||||
#include "shared/source/helpers/hw_info.h"
|
||||
#include "device_binary_format/patchtokens_tests.h"
|
||||
#include "test.h"
|
||||
|
||||
TEST(IsDeviceBinaryFormatAr, GivenValidBinaryReturnTrue) {
|
||||
auto emptyArchive = ArrayRef<const uint8_t>::fromAny(NEO::Ar::arMagic.begin(), NEO::Ar::arMagic.size());
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Archive>(emptyArchive));
|
||||
}
|
||||
|
||||
TEST(IsDeviceBinaryFormatAr, GivenInvalidBinaryReturnTrue) {
|
||||
const uint8_t binary[] = "not_ar";
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Archive>(binary));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryAr, WhenFailedToDecodeArThenUnpackingFails) {
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>({}, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty()) << unpackWarnings;
|
||||
EXPECT_STREQ("Not an AR archive - mismatched file signature", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryAr, WhenFailedToFindMatchingBinariesThenUnpackingFails) {
|
||||
auto emptyArchive = ArrayRef<const uint8_t>::fromAny(NEO::Ar::arMagic.begin(), NEO::Ar::arMagic.size());
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>(emptyArchive, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty()) << unpackWarnings;
|
||||
EXPECT_STREQ("Couldn't find matching binary in AR archive", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryAr, WhenMultipleBinariesMatchedThenChooseBestMatch) {
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
NEO::Ar::ArEncoder encoder;
|
||||
std::string requiredProduct = NEO::hardwarePrefix[productFamily];
|
||||
std::string requiredStepping = std::to_string(programTokens.header->SteppingId);
|
||||
std::string requiredPointerSize = (programTokens.header->GPUPointerSizeInBytes == 4) ? "32" : "64";
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "." + requiredProduct, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "." + requiredProduct + "." + requiredStepping, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "unk." + requiredStepping, programTokens.storage));
|
||||
|
||||
NEO::TargetDevice target;
|
||||
target.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
target.stepping = programTokens.header->SteppingId;
|
||||
target.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
auto arData = encoder.encode();
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>(arData, requiredProduct, target, unpackErrors, unpackWarnings);
|
||||
EXPECT_TRUE(unpackErrors.empty()) << unpackErrors;
|
||||
EXPECT_TRUE(unpackWarnings.empty()) << unpackWarnings;
|
||||
|
||||
unpackErrors.clear();
|
||||
unpackWarnings.clear();
|
||||
auto decodedAr = NEO::Ar::decodeAr(arData, unpackErrors, unpackWarnings);
|
||||
EXPECT_NE(nullptr, decodedAr.magic);
|
||||
ASSERT_EQ(4U, decodedAr.files.size());
|
||||
EXPECT_EQ(unpacked.deviceBinary.begin(), decodedAr.files[2].fileData.begin());
|
||||
EXPECT_EQ(unpacked.deviceBinary.size(), decodedAr.files[2].fileData.size());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryAr, WhenBestMatchIsntFullMatchThenChooseBestMatchButEmitWarnings) {
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
NEO::Ar::ArEncoder encoder;
|
||||
std::string requiredProduct = NEO::hardwarePrefix[productFamily];
|
||||
std::string requiredStepping = std::to_string(programTokens.header->SteppingId);
|
||||
std::string requiredPointerSize = (programTokens.header->GPUPointerSizeInBytes == 4) ? "32" : "64";
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "." + requiredProduct, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "unk." + requiredStepping, programTokens.storage));
|
||||
|
||||
NEO::TargetDevice target;
|
||||
target.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
target.stepping = programTokens.header->SteppingId;
|
||||
target.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
auto arData = encoder.encode();
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>(arData, requiredProduct, target, unpackErrors, unpackWarnings);
|
||||
EXPECT_TRUE(unpackErrors.empty()) << unpackErrors;
|
||||
EXPECT_FALSE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Couldn't find perfectly matched binary (right stepping) in AR, using best usable", unpackWarnings.c_str());
|
||||
|
||||
unpackErrors.clear();
|
||||
unpackWarnings.clear();
|
||||
auto decodedAr = NEO::Ar::decodeAr(arData, unpackErrors, unpackWarnings);
|
||||
EXPECT_NE(nullptr, decodedAr.magic);
|
||||
ASSERT_EQ(3U, decodedAr.files.size());
|
||||
EXPECT_EQ(unpacked.deviceBinary.begin(), decodedAr.files[1].fileData.begin());
|
||||
EXPECT_EQ(unpacked.deviceBinary.size(), decodedAr.files[1].fileData.size());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryAr, WhenFailedToUnpackBestMatchThenTryUnpackingAnyUsable) {
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
PatchTokensTestData::ValidEmptyProgram programTokensWrongTokenVersion;
|
||||
programTokensWrongTokenVersion.headerMutable->Version -= 1;
|
||||
NEO::Ar::ArEncoder encoder;
|
||||
std::string requiredProduct = NEO::hardwarePrefix[productFamily];
|
||||
std::string requiredStepping = std::to_string(programTokens.header->SteppingId);
|
||||
std::string requiredPointerSize = (programTokens.header->GPUPointerSizeInBytes == 4) ? "32" : "64";
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "." + requiredProduct, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "." + requiredProduct + "." + requiredStepping, programTokensWrongTokenVersion.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "unk." + requiredStepping, programTokens.storage));
|
||||
|
||||
NEO::TargetDevice target;
|
||||
target.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
target.stepping = programTokens.header->SteppingId;
|
||||
target.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
auto arData = encoder.encode();
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>(arData, requiredProduct, target, unpackErrors, unpackWarnings);
|
||||
EXPECT_TRUE(unpackErrors.empty()) << unpackErrors;
|
||||
EXPECT_FALSE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Couldn't find perfectly matched binary (right stepping) in AR, using best usable", unpackWarnings.c_str());
|
||||
|
||||
unpackErrors.clear();
|
||||
unpackWarnings.clear();
|
||||
auto decodedAr = NEO::Ar::decodeAr(arData, unpackErrors, unpackWarnings);
|
||||
EXPECT_NE(nullptr, decodedAr.magic);
|
||||
ASSERT_EQ(4U, decodedAr.files.size());
|
||||
EXPECT_EQ(unpacked.deviceBinary.begin(), decodedAr.files[1].fileData.begin());
|
||||
EXPECT_EQ(unpacked.deviceBinary.size(), decodedAr.files[1].fileData.size());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryAr, WhenCouldFindBinaryWithRightPointerSizeThenUnpackingFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
NEO::Ar::ArEncoder encoder;
|
||||
std::string requiredProduct = NEO::hardwarePrefix[productFamily];
|
||||
std::string requiredStepping = std::to_string(programTokens.header->SteppingId);
|
||||
std::string requiredPointerSize = (programTokens.header->GPUPointerSizeInBytes == 4) ? "32" : "64";
|
||||
std::string wrongPointerSize = (programTokens.header->GPUPointerSizeInBytes == 8) ? "32" : "64";
|
||||
ASSERT_TRUE(encoder.appendFileEntry(wrongPointerSize, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(wrongPointerSize + "." + requiredProduct, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(wrongPointerSize + "." + requiredProduct + "." + requiredStepping, programTokens.storage));
|
||||
ASSERT_TRUE(encoder.appendFileEntry(requiredPointerSize + "unk." + requiredStepping, programTokens.storage));
|
||||
|
||||
NEO::TargetDevice target;
|
||||
target.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
target.stepping = programTokens.header->SteppingId;
|
||||
target.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
auto arData = encoder.encode();
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>(arData, requiredProduct, target, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpacked.format);
|
||||
EXPECT_TRUE(unpacked.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty()) << unpackWarnings;
|
||||
EXPECT_STREQ("Couldn't find matching binary in AR archive", unpackErrors.c_str());
|
||||
}
|
||||
@@ -1,397 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/compiler_interface/intermediate_representations.h"
|
||||
#include "shared/source/device_binary_format/device_binary_formats.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
||||
#include "shared/source/device_binary_format/elf/ocl_elf.h"
|
||||
#include "shared/source/program/program_info.h"
|
||||
#include "device_binary_format/patchtokens_tests.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
||||
TEST(IsDeviceBinaryFormatOclElf, GivenElfThenReturnsTrueIfProperElfFileTypeDetected) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_DEBUG;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_SOURCE;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_NONE;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_EXEC;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_32> elfEnc32;
|
||||
elfEnc32.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc32.encode()));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, WhenFailedToDecodeElfThenUnpackingFails) {
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>({}, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Invalid or missing ELF header", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenNotOclElfThenUnpackingFails) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Not OCL ELF file type", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfThenSetsProperOutputFormat) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(NEO::spirvMagic.begin(), NEO::spirvMagic.size()));
|
||||
auto elfData = elfEnc64.encode();
|
||||
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::OclLibrary, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(unpackResult.intermediateRepresentation));
|
||||
EXPECT_EQ(NEO::spirvMagic.size(), unpackResult.intermediateRepresentation.size());
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, NEO::Elf::SectionNamesOpenCl::llvmObject, ArrayRef<const uint8_t>::fromAny(NEO::llvmBcMagic.begin(), NEO::llvmBcMagic.size()));
|
||||
elfData = elfEnc64.encode();
|
||||
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::OclCompiledObject, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(NEO::isLlvmBitcode(unpackResult.intermediateRepresentation));
|
||||
EXPECT_EQ(NEO::llvmBcMagic.size(), unpackResult.intermediateRepresentation.size());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenValidOclElfExecutableThenReadsAllSectionProperly) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
targetDevice.stepping = patchtokensProgram.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
|
||||
const uint8_t intermediateRepresentation[] = "235711";
|
||||
const uint8_t debugData[] = "313739";
|
||||
std::string buildOptions = "buildOpts";
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, buildOptions);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_DEBUG, NEO::Elf::SectionNamesOpenCl::buildOptions, debugData);
|
||||
{
|
||||
auto encWithLlvm = elfEnc64;
|
||||
encWithLlvm.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, NEO::Elf::SectionNamesOpenCl::llvmObject, intermediateRepresentation);
|
||||
auto elfData = encWithLlvm.encode();
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
ASSERT_EQ(patchtokensProgram.storage.size(), unpackResult.deviceBinary.size());
|
||||
ASSERT_EQ(sizeof(debugData), unpackResult.debugData.size());
|
||||
ASSERT_EQ(buildOptions.size() + 1, unpackResult.buildOptions.size());
|
||||
ASSERT_EQ(sizeof(intermediateRepresentation), unpackResult.intermediateRepresentation.size());
|
||||
|
||||
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpackResult.deviceBinary.begin(), unpackResult.deviceBinary.size()));
|
||||
EXPECT_STREQ(buildOptions.c_str(), unpackResult.buildOptions.begin());
|
||||
EXPECT_EQ(0, memcmp(debugData, unpackResult.debugData.begin(), unpackResult.debugData.size()));
|
||||
EXPECT_EQ(0, memcmp(intermediateRepresentation, unpackResult.intermediateRepresentation.begin(), unpackResult.intermediateRepresentation.size()));
|
||||
}
|
||||
{
|
||||
auto encWithSpirV = elfEnc64;
|
||||
encWithSpirV.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, intermediateRepresentation);
|
||||
auto elfData = encWithSpirV.encode();
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
ASSERT_EQ(patchtokensProgram.storage.size(), unpackResult.deviceBinary.size());
|
||||
ASSERT_EQ(sizeof(debugData), unpackResult.debugData.size());
|
||||
ASSERT_EQ(buildOptions.size() + 1, unpackResult.buildOptions.size());
|
||||
ASSERT_EQ(sizeof(intermediateRepresentation), unpackResult.intermediateRepresentation.size());
|
||||
|
||||
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpackResult.deviceBinary.begin(), unpackResult.deviceBinary.size()));
|
||||
EXPECT_STREQ(buildOptions.c_str(), unpackResult.buildOptions.begin());
|
||||
EXPECT_EQ(0, memcmp(debugData, unpackResult.debugData.begin(), unpackResult.debugData.size()));
|
||||
EXPECT_EQ(0, memcmp(intermediateRepresentation, unpackResult.intermediateRepresentation.begin(), unpackResult.intermediateRepresentation.size()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfExecutableWithUnhandledSectionThenUnpackingFails) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_NOBITS, "my_data", {});
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Unhandled ELF section", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfExecutableWhenPatchtokensBinaryIsBrokenThenReadsAllSectionProperly) {
|
||||
const uint8_t intermediateRepresentation[] = "235711";
|
||||
const uint8_t debugData[] = "313739";
|
||||
const uint8_t deviceBinary[] = "not_patchtokens";
|
||||
std::string buildOptions = "buildOpts";
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, deviceBinary);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, buildOptions);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_DEBUG, NEO::Elf::SectionNamesOpenCl::buildOptions, debugData);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, intermediateRepresentation);
|
||||
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Invalid program header", unpackErrors.c_str());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_FALSE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinaryOclElf, WhenUsedAsSingleDeviceBinaryThenDecodingFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
;
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
auto elfData = elfEnc64.encode();
|
||||
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
targetDevice.stepping = patchtokensProgram.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
|
||||
NEO::SingleDeviceBinary deviceBinary;
|
||||
deviceBinary.targetDevice = targetDevice;
|
||||
deviceBinary.deviceBinary = elfData;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::DecodeError error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(programInfo, deviceBinary, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Device binary format is packed", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingEmptyDataThenEmptyOclElfIsEmitted) {
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
|
||||
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
|
||||
EXPECT_EQ(0U, elf.elfFileHeader->shNum);
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWithUnknownIntermediateRepresentationThenFail) {
|
||||
const uint8_t intermediateRepresentation[] = "not_llvm_and_not_spirv";
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
singleBinary.intermediateRepresentation = intermediateRepresentation;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packedData.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_FALSE(packErrors.empty());
|
||||
EXPECT_STREQ("Unknown intermediate representation format", packErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWitIntermediateRepresentationThenChoosesProperSectionBasedOnMagic) {
|
||||
using namespace NEO::Elf;
|
||||
auto spirV = NEO::spirvMagic;
|
||||
auto llvmBc = NEO::llvmBcMagic;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
|
||||
{
|
||||
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(spirV.begin(), spirV.size());
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_FALSE(packedData.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
|
||||
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
|
||||
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
|
||||
|
||||
auto spirVSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
ASSERT_NE(nullptr, spirVSection);
|
||||
ASSERT_EQ(spirV.size(), spirVSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(spirV.begin(), spirVSection->data.begin(), spirV.size()));
|
||||
}
|
||||
|
||||
{
|
||||
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(llvmBc.begin(), llvmBc.size());
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_FALSE(packedData.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
|
||||
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
|
||||
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
|
||||
|
||||
auto llvmSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_LLVM_BINARY; });
|
||||
ASSERT_NE(nullptr, llvmSection);
|
||||
ASSERT_EQ(llvmBc.size(), llvmSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(llvmBc.begin(), llvmSection->data.begin(), llvmBc.size()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryThenSectionsAreProperlyPopulated) {
|
||||
using namespace NEO::Elf;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
|
||||
auto spirV = NEO::spirvMagic;
|
||||
const uint8_t debugData[] = "313739";
|
||||
const uint8_t deviceBinary[] = "23571113";
|
||||
std::string buildOptions = "buildOpts";
|
||||
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(spirV.begin(), spirV.size());
|
||||
singleBinary.debugData = debugData;
|
||||
singleBinary.deviceBinary = deviceBinary;
|
||||
singleBinary.buildOptions = buildOptions;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
auto spirvSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
|
||||
auto deviceBinarySection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_BINARY; });
|
||||
|
||||
auto deviceDebugSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_DEBUG; });
|
||||
|
||||
auto buildOptionsSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_OPTIONS; });
|
||||
|
||||
ASSERT_NE(nullptr, spirvSection);
|
||||
ASSERT_EQ(spirV.size(), spirvSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(spirV.begin(), spirvSection->data.begin(), spirV.size()));
|
||||
|
||||
ASSERT_NE(nullptr, deviceBinarySection);
|
||||
ASSERT_EQ(sizeof(deviceBinary), deviceBinarySection->data.size());
|
||||
EXPECT_EQ(0, memcmp(deviceBinary, deviceBinarySection->data.begin(), sizeof(deviceBinary)));
|
||||
|
||||
ASSERT_NE(nullptr, deviceDebugSection);
|
||||
ASSERT_EQ(sizeof(debugData), deviceDebugSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(debugData, deviceDebugSection->data.begin(), sizeof(debugData)));
|
||||
|
||||
ASSERT_NE(nullptr, buildOptionsSection);
|
||||
ASSERT_EQ(buildOptions.size(), buildOptionsSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(buildOptions.c_str(), buildOptionsSection->data.begin(), buildOptions.size()));
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/device_binary_formats.h"
|
||||
#include "shared/source/program/program_info.h"
|
||||
#include "device_binary_format/patchtokens_tests.h"
|
||||
#include "test.h"
|
||||
|
||||
TEST(IsDeviceBinaryFormatPatchtokens, GivenValidBinaryReturnTrue) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage));
|
||||
}
|
||||
|
||||
TEST(IsDeviceBinaryFormatPatchtokens, GivenInvalidBinaryReturnTrue) {
|
||||
const uint8_t binary[] = "not_patchtokens";
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(binary));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenFailedToDecodeHeaderThenUnpackingFails) {
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>({}, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Invalid program header", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryAndMatchedWithRequestedTargetDeviceThenReturnSelf) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
EXPECT_EQ(targetDevice.coreFamily, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(targetDevice.stepping, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(targetDevice.maxPointerSizeInBytes, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_FALSE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_EQ(programTokens.storage.data(), unpackResult.deviceBinary.begin());
|
||||
EXPECT_EQ(programTokens.storage.size(), unpackResult.deviceBinary.size());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryForDifferentCoreFamilyDeviceThenUnpackingFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device + 1);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryWithUnsupportedPatchTokensVerionThenUnpackingFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
programTokens.headerMutable->Version += 1;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryWithUnsupportedPointerSizeThenUnpackingFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
programTokens.headerMutable->GPUPointerSizeInBytes = 8U;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = 4U;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinaryPatchtokens, GivenInvalidBinaryThenReturnError) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programInfo, singleBinary, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinaryPatchtokens, GivenValidBinaryThenOutputIsProperlyPopulated) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
singleBinary.deviceBinary = programTokens.storage;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programInfo, singleBinary, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, error);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
ASSERT_EQ(1U, programInfo.kernelInfos.size());
|
||||
}
|
||||
@@ -1,275 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/ar/ar_encoder.h"
|
||||
#include "shared/source/device_binary_format/device_binary_formats.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
||||
#include "shared/source/device_binary_format/elf/ocl_elf.h"
|
||||
#include "shared/source/program/program_info.h"
|
||||
#include "device_binary_format/patchtokens_tests.h"
|
||||
#include "test.h"
|
||||
|
||||
TEST(DecodeError, WhenStringRepresentationIsNeededThenAsStringEncodesProperly) {
|
||||
EXPECT_STREQ("decoded successfully", NEO::asString(NEO::DecodeError::Success));
|
||||
EXPECT_STREQ("in undefined status", NEO::asString(NEO::DecodeError::Undefined));
|
||||
EXPECT_STREQ("with invalid binary", NEO::asString(NEO::DecodeError::InvalidBinary));
|
||||
EXPECT_STREQ("with unhandled binary", NEO::asString(NEO::DecodeError::UnhandledBinary));
|
||||
}
|
||||
|
||||
TEST(IsAnyDeviceBinaryFormat, GivenNoneOfKnownFormatsThenReturnsFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
EXPECT_FALSE(NEO::isAnyDeviceBinaryFormat(data));
|
||||
}
|
||||
|
||||
TEST(IsAnyDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsTrue) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
EXPECT_TRUE(NEO::isAnyDeviceBinaryFormat(patchtokensProgram.storage));
|
||||
}
|
||||
|
||||
TEST(IsAnyDeviceBinaryFormat, GivenOclElfFormatThenReturnsTrue) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_TRUE(NEO::isAnyDeviceBinaryFormat(elfEnc.encode()));
|
||||
}
|
||||
|
||||
TEST(IsAnyDeviceBinaryFormat, GivenArFormatThenReturnsTrue) {
|
||||
EXPECT_TRUE(NEO::isAnyDeviceBinaryFormat(ArrayRef<const uint8_t>::fromAny(NEO::Ar::arMagic.begin(), NEO::Ar::arMagic.size())));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinary, GivenUnknownBinaryThenReturnError) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
ConstStringRef requestedProductAbbreviation = "unk";
|
||||
NEO::TargetDevice requestedTargetDevice;
|
||||
std::string outErrors;
|
||||
std::string outWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary(data, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_TRUE(unpacked.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpacked.format);
|
||||
EXPECT_EQ(0U, unpacked.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpacked.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpacked.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(outWarnings.empty());
|
||||
EXPECT_STREQ("Unknown format", outErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinary, GivenPatchtoknsBinaryThenReturnSelf) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
ConstStringRef requestedProductAbbreviation = "unk";
|
||||
NEO::TargetDevice requestedTargetDevice;
|
||||
requestedTargetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
requestedTargetDevice.stepping = patchtokensProgram.header->SteppingId;
|
||||
requestedTargetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
std::string outErrors;
|
||||
std::string outWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary(patchtokensProgram.storage, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_FALSE(unpacked.deviceBinary.empty());
|
||||
EXPECT_EQ(patchtokensProgram.storage.data(), unpacked.deviceBinary.begin());
|
||||
EXPECT_EQ(patchtokensProgram.storage.size(), unpacked.deviceBinary.size());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
EXPECT_EQ(requestedTargetDevice.coreFamily, unpacked.targetDevice.coreFamily);
|
||||
EXPECT_EQ(requestedTargetDevice.stepping, unpacked.targetDevice.stepping);
|
||||
EXPECT_EQ(patchtokensProgram.header->GPUPointerSizeInBytes, unpacked.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(outWarnings.empty());
|
||||
EXPECT_TRUE(outErrors.empty());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinary, GivenOclElfBinaryThenReturnPatchtokensBinary) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
|
||||
ConstStringRef requestedProductAbbreviation = "unk";
|
||||
NEO::TargetDevice requestedTargetDevice;
|
||||
requestedTargetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
requestedTargetDevice.stepping = patchtokensProgram.header->SteppingId;
|
||||
requestedTargetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
std::string outErrors;
|
||||
std::string outWarnings;
|
||||
auto elfData = elfEnc.encode();
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary(elfData, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
EXPECT_EQ(requestedTargetDevice.coreFamily, unpacked.targetDevice.coreFamily);
|
||||
EXPECT_EQ(requestedTargetDevice.stepping, unpacked.targetDevice.stepping);
|
||||
EXPECT_EQ(patchtokensProgram.header->GPUPointerSizeInBytes, unpacked.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(outWarnings.empty());
|
||||
EXPECT_TRUE(outErrors.empty());
|
||||
|
||||
EXPECT_FALSE(unpacked.deviceBinary.empty());
|
||||
ASSERT_EQ(patchtokensProgram.storage.size(), unpacked.deviceBinary.size());
|
||||
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpacked.deviceBinary.begin(), unpacked.deviceBinary.size()));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinary, GivenArBinaryWithOclElfThenReturnPatchtokensBinary) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
|
||||
NEO::TargetDevice requestedTargetDevice;
|
||||
requestedTargetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
requestedTargetDevice.stepping = patchtokensProgram.header->SteppingId;
|
||||
requestedTargetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
std::string outErrors;
|
||||
std::string outWarnings;
|
||||
auto elfData = elfEnc.encode();
|
||||
|
||||
std::string requiredProduct = NEO::hardwarePrefix[productFamily];
|
||||
std::string requiredStepping = std::to_string(patchtokensProgram.header->SteppingId);
|
||||
std::string requiredPointerSize = (patchtokensProgram.header->GPUPointerSizeInBytes == 4) ? "32" : "64";
|
||||
NEO::Ar::ArEncoder arEnc(true);
|
||||
ASSERT_TRUE(arEnc.appendFileEntry(requiredPointerSize + "." + requiredProduct + "." + requiredStepping, elfData));
|
||||
auto arData = arEnc.encode();
|
||||
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary(arData, requiredProduct, requestedTargetDevice, outErrors, outWarnings);
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
EXPECT_EQ(requestedTargetDevice.coreFamily, unpacked.targetDevice.coreFamily);
|
||||
EXPECT_EQ(requestedTargetDevice.stepping, unpacked.targetDevice.stepping);
|
||||
EXPECT_EQ(patchtokensProgram.header->GPUPointerSizeInBytes, unpacked.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(outWarnings.empty()) << outWarnings;
|
||||
EXPECT_TRUE(outErrors.empty()) << outErrors;
|
||||
|
||||
EXPECT_FALSE(unpacked.deviceBinary.empty());
|
||||
ASSERT_EQ(patchtokensProgram.storage.size(), unpacked.deviceBinary.size());
|
||||
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpacked.deviceBinary.begin(), unpacked.deviceBinary.size()));
|
||||
}
|
||||
|
||||
TEST(IsAnyPackedDeviceBinaryFormat, GivenUnknownFormatThenReturnFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
EXPECT_FALSE(NEO::isAnyPackedDeviceBinaryFormat(data));
|
||||
}
|
||||
|
||||
TEST(IsAnyPackedDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsFalse) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
EXPECT_FALSE(NEO::isAnyPackedDeviceBinaryFormat(patchtokensProgram.storage));
|
||||
}
|
||||
|
||||
TEST(IsAnyPackedDeviceBinaryFormat, GivenOclElfFormatThenReturnsTrue) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_TRUE(NEO::isAnyPackedDeviceBinaryFormat(elfEnc.encode()));
|
||||
}
|
||||
|
||||
TEST(IsAnyPackedDeviceBinaryFormat, GivenArFormatThenReturnsTrue) {
|
||||
EXPECT_TRUE(NEO::isAnyPackedDeviceBinaryFormat(ArrayRef<const uint8_t>::fromAny(NEO::Ar::arMagic.begin(), NEO::Ar::arMagic.size())));
|
||||
}
|
||||
|
||||
TEST(IsAnySingleDeviceBinaryFormat, GivenUnknownFormatThenReturnFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
EXPECT_FALSE(NEO::isAnySingleDeviceBinaryFormat(data));
|
||||
}
|
||||
|
||||
TEST(IsAnySingleDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsTrue) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
EXPECT_TRUE(NEO::isAnySingleDeviceBinaryFormat(patchtokensProgram.storage));
|
||||
}
|
||||
|
||||
TEST(IsAnySingleDeviceBinaryFormat, GivenOclElfFormatThenReturnsFalse) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_FALSE(NEO::isAnySingleDeviceBinaryFormat(elfEnc.encode()));
|
||||
}
|
||||
|
||||
TEST(IsAnySingleDeviceBinaryFormat, GivenArFormatThenReturnsFalse) {
|
||||
EXPECT_FALSE(NEO::isAnySingleDeviceBinaryFormat(ArrayRef<const uint8_t>::fromAny(NEO::Ar::arMagic.begin(), NEO::Ar::arMagic.size())));
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinary, GivenUnknownFormatThenReturnFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
NEO::ProgramInfo programInfo;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
NEO::SingleDeviceBinary bin;
|
||||
bin.deviceBinary = data;
|
||||
NEO::DecodeError status;
|
||||
NEO::DeviceBinaryFormat format;
|
||||
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, status);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, format);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_STREQ("Unknown format", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinary, GivenPatchTokensFormatThenDecodingSucceeds) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
NEO::ProgramInfo programInfo;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
NEO::SingleDeviceBinary bin;
|
||||
bin.deviceBinary = patchtokensProgram.storage;
|
||||
NEO::DecodeError status;
|
||||
NEO::DeviceBinaryFormat format;
|
||||
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, status);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, format);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinary, GivenOclElfFormatThenDecodingFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
|
||||
auto elfData = elfEnc.encode();
|
||||
NEO::ProgramInfo programInfo;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
NEO::SingleDeviceBinary bin;
|
||||
bin.deviceBinary = elfData;
|
||||
NEO::DecodeError status;
|
||||
NEO::DeviceBinaryFormat format;
|
||||
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, status);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::OclElf, format);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_STREQ("Device binary format is packed", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinary, GivenArFormatThenDecodingFails) {
|
||||
NEO::Ar::ArEncoder arEnc;
|
||||
auto arData = arEnc.encode();
|
||||
NEO::ProgramInfo programInfo;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
NEO::SingleDeviceBinary bin;
|
||||
bin.deviceBinary = arData;
|
||||
NEO::DecodeError status;
|
||||
NEO::DeviceBinaryFormat format;
|
||||
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, status);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Archive, format);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_STREQ("Device binary format is packed", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinary, GivenRequestToPackThenUsesOclElfFormat) {
|
||||
NEO::SingleDeviceBinary deviceBinary;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packed = NEO::packDeviceBinary(deviceBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packed));
|
||||
}
|
||||
@@ -1,343 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO::Elf;
|
||||
|
||||
TEST(ElfDecoder, WhenEmptyDataThenElfHeaderDecodingFails) {
|
||||
ArrayRef<const uint8_t> empty;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(empty));
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(empty));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidHaderThenElfHeaderDecodingSucceeds) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_EQ(&header64, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_EQ(&header32, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenNotEngoughDataThenElfHeaderDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
auto header64Data = ArrayRef<const uint8_t>::fromAny(&header64, 1U);
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>(header64Data.begin(), header64Data.begin() + header64Data.size() - 1)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
auto header32Data = ArrayRef<const uint8_t>::fromAny(&header32, 1U);
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>(header32Data.begin(), header32Data.begin() + header32Data.size() - 1)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenInvalidElfMagicThenElfHeaderDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.identity.magic[0] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
header.identity.magic[1] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
header.identity.magic[2] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
header.identity.magic[3] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
EXPECT_EQ(&header, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenMismatchedClassThenElfHeaderDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenNotElfThenCheckNumBitsReturnsClassNone) {
|
||||
ArrayRef<const uint8_t> empty;
|
||||
EXPECT_EQ(EI_CLASS_NONE, getElfNumBits(empty));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidElfThenCheckNumBitsReturnsProperClass) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_EQ(EI_CLASS_64, getElfNumBits(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_EQ(EI_CLASS_32, getElfNumBits(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenNotElfThenIsElfReturnsFalse) {
|
||||
ArrayRef<const uint8_t> empty;
|
||||
EXPECT_FALSE(isElf(empty));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidElfThenIsElfReturnsTrue) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_TRUE(isElf(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_TRUE(isElf(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidEmptyElfThenHeaderIsProperlyDecodedAndNoWarningsOrErrorsEmitted) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header64, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(&header64, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
|
||||
decodeWarnings.clear();
|
||||
decodeErrors.clear();
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
auto elf32 = decodeElf<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header32, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(&header32, elf32.elfFileHeader);
|
||||
EXPECT_TRUE(elf32.programHeaders.empty());
|
||||
EXPECT_TRUE(elf32.sectionHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenInvalidElfHeaderThenDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.identity.magic[0] = 5;
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Invalid or missing ELF header", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderTableOffsetThenDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = sizeof(header) + 1;
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds program headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderTableOffsetThenDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = sizeof(header) + 1;
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds section headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidProgramHeaderTableEntriesThenDecodingSucceedsAndNoWarningsOrErrorsEmitted) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = header.ehSize;
|
||||
header.phNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader0;
|
||||
programHeader0.fileSz = sizeof(programHeader0) * 2;
|
||||
programHeader0.offset = header.phOff;
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
ASSERT_EQ(2U, elf64.programHeaders.size());
|
||||
EXPECT_EQ(reinterpret_cast<decltype(programHeader0) *>(storage.data() + header.phOff), elf64.programHeaders[0].header);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(programHeader1) *>(storage.data() + header.phOff + header.phEntSize), elf64.programHeaders[1].header);
|
||||
EXPECT_TRUE(elf64.programHeaders[1].data.empty());
|
||||
EXPECT_FALSE(elf64.programHeaders[0].data.empty());
|
||||
EXPECT_EQ(storage.data() + programHeader0.offset, elf64.programHeaders[0].data.begin());
|
||||
EXPECT_EQ(programHeader0.fileSz, elf64.programHeaders[0].data.size());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderTableEntriesThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = header.ehSize;
|
||||
header.phNum = 3;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader0;
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds program headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderDataThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = header.ehSize;
|
||||
header.phNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader0;
|
||||
programHeader0.fileSz = sizeof(programHeader0) * 2;
|
||||
programHeader0.offset = header.phOff;
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader1;
|
||||
programHeader1.fileSz = sizeof(programHeader0) * 3;
|
||||
programHeader1.offset = header.phOff;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds program header offset/filesz, program header idx : 1", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidSectionHeaderTableEntriesThenDecodingSucceedsAndNoWarningsOrErrorsEmitted) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
sectionHeader0.size = sizeof(sectionHeader0) * 2;
|
||||
sectionHeader0.offset = header.shOff;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
ASSERT_EQ(2U, elf64.sectionHeaders.size());
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader0) *>(storage.data() + header.shOff), elf64.sectionHeaders[0].header);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader1) *>(storage.data() + header.shOff + header.shEntSize), elf64.sectionHeaders[1].header);
|
||||
EXPECT_TRUE(elf64.sectionHeaders[1].data.empty());
|
||||
EXPECT_FALSE(elf64.sectionHeaders[0].data.empty());
|
||||
EXPECT_EQ(storage.data() + sectionHeader0.offset, elf64.sectionHeaders[0].data.begin());
|
||||
EXPECT_EQ(sectionHeader0.size, elf64.sectionHeaders[0].data.size());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderTableEntriesThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 3;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds section headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderDataThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
sectionHeader0.size = sizeof(sectionHeader0) * 2;
|
||||
sectionHeader0.offset = header.shOff;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
sectionHeader1.size = sizeof(sectionHeader0) * 3;
|
||||
sectionHeader1.offset = header.shOff;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds section header offset/size, section header idx : 1", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenSectionDoesNotHaveDataInFileThenDataIsSetAsEmpty) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
sectionHeader0.size = sizeof(sectionHeader0) * 2;
|
||||
sectionHeader0.offset = header.shOff;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
sectionHeader1.size = sizeof(sectionHeader0) * 3;
|
||||
sectionHeader1.offset = header.shOff;
|
||||
sectionHeader1.type = SHT_NOBITS;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
ASSERT_EQ(2U, elf64.sectionHeaders.size());
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader0) *>(storage.data() + header.shOff), elf64.sectionHeaders[0].header);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader1) *>(storage.data() + header.shOff + header.shEntSize), elf64.sectionHeaders[1].header);
|
||||
EXPECT_TRUE(elf64.sectionHeaders[1].data.empty());
|
||||
EXPECT_FALSE(elf64.sectionHeaders[0].data.empty());
|
||||
EXPECT_EQ(storage.data() + sectionHeader0.offset, elf64.sectionHeaders[0].data.begin());
|
||||
EXPECT_EQ(sectionHeader0.size, elf64.sectionHeaders[0].data.size());
|
||||
}
|
||||
@@ -1,457 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
||||
#include "shared/source/utilities/range.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO::Elf;
|
||||
|
||||
TEST(ElfEncoder, WhenEmptyDataThenEncodedElfContainsOnlyHeader) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
auto &identity64 = header64.identity;
|
||||
EXPECT_EQ(elfMagic[0], identity64.magic[0]);
|
||||
EXPECT_EQ(elfMagic[1], identity64.magic[1]);
|
||||
EXPECT_EQ(elfMagic[2], identity64.magic[2]);
|
||||
EXPECT_EQ(elfMagic[3], identity64.magic[3]);
|
||||
EXPECT_EQ(EI_CLASS_64, identity64.eClass);
|
||||
EXPECT_EQ(EI_DATA_LITTLE_ENDIAN, identity64.data);
|
||||
EXPECT_EQ(EV_CURRENT, identity64.version);
|
||||
EXPECT_EQ(0U, identity64.osAbi);
|
||||
EXPECT_EQ(0U, identity64.abiVersion);
|
||||
EXPECT_EQ(ET_NONE, header64.type);
|
||||
EXPECT_EQ(EM_NONE, header64.machine);
|
||||
EXPECT_EQ(1U, header64.version);
|
||||
EXPECT_EQ(0U, header64.entry);
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(0U, header64.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), header64.ehSize);
|
||||
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_64>), header64.phEntSize);
|
||||
EXPECT_EQ(0U, header64.phNum);
|
||||
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_64>), header64.shEntSize);
|
||||
EXPECT_EQ(0U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
ElfEncoder<EI_CLASS_32> elfEncoder32(false, false);
|
||||
auto elfData32 = elfEncoder32.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>), elfData32.size());
|
||||
auto &header32 = *reinterpret_cast<ElfFileHeader<EI_CLASS_32> *>(elfData32.data());
|
||||
auto &identity32 = header32.identity;
|
||||
EXPECT_EQ(elfMagic[0], identity32.magic[0]);
|
||||
EXPECT_EQ(elfMagic[1], identity32.magic[1]);
|
||||
EXPECT_EQ(elfMagic[2], identity32.magic[2]);
|
||||
EXPECT_EQ(elfMagic[3], identity32.magic[3]);
|
||||
EXPECT_EQ(EI_CLASS_32, identity32.eClass);
|
||||
EXPECT_EQ(EI_DATA_LITTLE_ENDIAN, identity32.data);
|
||||
EXPECT_EQ(EV_CURRENT, identity32.version);
|
||||
EXPECT_EQ(0U, identity32.osAbi);
|
||||
EXPECT_EQ(0U, identity32.abiVersion);
|
||||
EXPECT_EQ(ET_NONE, header32.type);
|
||||
EXPECT_EQ(EM_NONE, header32.machine);
|
||||
EXPECT_EQ(1U, header32.version);
|
||||
EXPECT_EQ(0U, header32.entry);
|
||||
EXPECT_EQ(0U, header32.phOff);
|
||||
EXPECT_EQ(0U, header32.shOff);
|
||||
EXPECT_EQ(0U, header32.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>), header32.ehSize);
|
||||
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_32>), header32.phEntSize);
|
||||
EXPECT_EQ(0U, header32.phNum);
|
||||
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_32>), header32.shEntSize);
|
||||
EXPECT_EQ(0U, header32.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header32.shStrNdx);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, GivenRequestForUndefAndSectionHeaderNamesSectionsWhenNotNeededThenNotEmitted) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(0U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, GivenRequestForUndefAndSectionHeaderNamesSectionsWhenNeededThenEmitted) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
|
||||
elfEncoder64.appendSection(SHT_NULL, ".my_name_is_important", {});
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
char expectedSectionNamesData[] = "\0.shstrtab\0.my_name_is_important";
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>) + alignUp(sizeof(expectedSectionNamesData), 8), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(0U, header64.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), header64.ehSize);
|
||||
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_64>), header64.phEntSize);
|
||||
EXPECT_EQ(0U, header64.phNum);
|
||||
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_64>), header64.shEntSize);
|
||||
EXPECT_EQ(3U, header64.shNum);
|
||||
EXPECT_EQ(2U, header64.shStrNdx);
|
||||
auto §Undef64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
auto §SkipMe64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>));
|
||||
auto §SectionNames64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + 2 * sizeof(ElfSectionHeader<EI_CLASS_64>));
|
||||
const char *sectionNames64Data = reinterpret_cast<char *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>));
|
||||
|
||||
EXPECT_EQ(0U, sectUndef64.name);
|
||||
EXPECT_EQ(SHT_NULL, sectUndef64.type);
|
||||
EXPECT_EQ(SHF_NONE, sectUndef64.flags);
|
||||
EXPECT_EQ(0U, sectUndef64.addr);
|
||||
EXPECT_EQ(0U, sectUndef64.offset);
|
||||
EXPECT_EQ(0U, sectUndef64.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectUndef64.link);
|
||||
EXPECT_EQ(0U, sectUndef64.info);
|
||||
EXPECT_EQ(0U, sectUndef64.addralign);
|
||||
EXPECT_EQ(0U, sectUndef64.entsize);
|
||||
|
||||
EXPECT_EQ(11U, sectSkipMe64.name);
|
||||
EXPECT_EQ(SHT_NULL, sectSkipMe64.type);
|
||||
EXPECT_EQ(SHF_NONE, sectSkipMe64.flags);
|
||||
EXPECT_EQ(0U, sectSkipMe64.addr);
|
||||
EXPECT_EQ(0U, sectSkipMe64.offset);
|
||||
EXPECT_EQ(0U, sectSkipMe64.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectSkipMe64.link);
|
||||
EXPECT_EQ(0U, sectSkipMe64.info);
|
||||
EXPECT_EQ(8U, sectSkipMe64.addralign);
|
||||
EXPECT_EQ(0U, sectSkipMe64.entsize);
|
||||
|
||||
EXPECT_EQ(1U, sectSectionNames64.name);
|
||||
EXPECT_EQ(SHT_STRTAB, sectSectionNames64.type);
|
||||
EXPECT_EQ(SHF_NONE, sectSectionNames64.flags);
|
||||
EXPECT_EQ(0U, sectSectionNames64.addr);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>), sectSectionNames64.offset);
|
||||
EXPECT_EQ(sizeof(expectedSectionNamesData), sectSectionNames64.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectSectionNames64.link);
|
||||
EXPECT_EQ(0U, sectSectionNames64.info);
|
||||
EXPECT_EQ(8U, sectSectionNames64.addralign);
|
||||
EXPECT_EQ(0U, sectSectionNames64.entsize);
|
||||
EXPECT_EQ(0, memcmp(expectedSectionNamesData, sectionNames64Data, sizeof(expectedSectionNamesData)));
|
||||
|
||||
ElfEncoder<EI_CLASS_32> elfEncoder32(true, true);
|
||||
elfEncoder32.appendSection(SHT_NULL, ".my_name_is_important", {});
|
||||
auto elfData32 = elfEncoder32.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>) + alignUp(sizeof(expectedSectionNamesData), 8), elfData32.size());
|
||||
auto &header32 = *reinterpret_cast<ElfFileHeader<EI_CLASS_32> *>(elfData32.data());
|
||||
EXPECT_EQ(header32.ehSize, header32.shOff);
|
||||
auto §SectionNames32 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_32> *>(elfData32.data() + sizeof(ElfFileHeader<EI_CLASS_32>) + 2 * sizeof(ElfSectionHeader<EI_CLASS_32>));
|
||||
const char *sectionNames32Data = reinterpret_cast<char *>(elfData32.data() + sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>));
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>), sectSectionNames32.offset);
|
||||
EXPECT_EQ(sizeof(expectedSectionNamesData), sectSectionNames32.size);
|
||||
EXPECT_EQ(0, memcmp(expectedSectionNamesData, sectionNames32Data, sizeof(expectedSectionNamesData)));
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionWithDataThenOffsetsAreProperlyUpdated) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSection(SHT_PROGBITS, ".my_name_is_not_important", data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>) + alignUp(sizeof(data), 8), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(1U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto §ProgBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
auto sectProgBitsData = elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>);
|
||||
EXPECT_EQ(0U, sectProgBits.name);
|
||||
EXPECT_EQ(SHT_PROGBITS, sectProgBits.type);
|
||||
EXPECT_EQ(SHF_NONE, sectProgBits.flags);
|
||||
EXPECT_EQ(0U, sectProgBits.addr);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>), sectProgBits.offset);
|
||||
EXPECT_EQ(sizeof(data), sectProgBits.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectProgBits.link);
|
||||
EXPECT_EQ(0U, sectProgBits.info);
|
||||
EXPECT_EQ(8U, sectProgBits.addralign);
|
||||
EXPECT_EQ(0U, sectProgBits.entsize);
|
||||
EXPECT_EQ(0, memcmp(data, sectProgBitsData, sizeof(data)));
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionWithoutDataThenOffsetsAreLeftIntact) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
elfEncoder64.appendSection(SHT_PROGBITS, ".my_name_is_not_important", {});
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(1U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto §ProgBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(0U, sectProgBits.name);
|
||||
EXPECT_EQ(SHT_PROGBITS, sectProgBits.type);
|
||||
EXPECT_EQ(SHF_NONE, sectProgBits.flags);
|
||||
EXPECT_EQ(0U, sectProgBits.addr);
|
||||
EXPECT_EQ(0U, sectProgBits.offset);
|
||||
EXPECT_EQ(0U, sectProgBits.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectProgBits.link);
|
||||
EXPECT_EQ(0U, sectProgBits.info);
|
||||
EXPECT_EQ(8U, sectProgBits.addralign);
|
||||
EXPECT_EQ(0U, sectProgBits.entsize);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionWithNoBitsTypeThenDataIsIgnored) {
|
||||
{
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSection(SHT_NOBITS, ".my_name_is_not_important", data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(1U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto §NoBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(0U, sectNoBits.name);
|
||||
EXPECT_EQ(SHT_NOBITS, sectNoBits.type);
|
||||
EXPECT_EQ(SHF_NONE, sectNoBits.flags);
|
||||
EXPECT_EQ(0U, sectNoBits.addr);
|
||||
EXPECT_EQ(0U, sectNoBits.offset);
|
||||
EXPECT_EQ(0U, sectNoBits.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectNoBits.link);
|
||||
EXPECT_EQ(0U, sectNoBits.info);
|
||||
EXPECT_EQ(8U, sectNoBits.addralign);
|
||||
EXPECT_EQ(0U, sectNoBits.entsize);
|
||||
}
|
||||
|
||||
{
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSection(static_cast<uint32_t>(SHT_NOBITS), ".my_name_is_not_important", data).size = sizeof(data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
|
||||
|
||||
auto §NoBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(0U, sectNoBits.offset);
|
||||
EXPECT_EQ(sizeof(data), sectNoBits.size);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSegmentWithDataThenOffsetsAreProperlyUpdated) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSegment(PT_LOAD, data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfProgramHeader<EI_CLASS_64>) + alignUp(sizeof(data), 8), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.phOff);
|
||||
EXPECT_EQ(1U, header64.phNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto &segLoad = *reinterpret_cast<ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
auto segLoadBitsData = elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfProgramHeader<EI_CLASS_64>);
|
||||
EXPECT_EQ(PT_LOAD, segLoad.type);
|
||||
EXPECT_EQ(PF_NONE, segLoad.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfProgramHeader<EI_CLASS_64>), segLoad.offset);
|
||||
EXPECT_EQ(0U, segLoad.vAddr);
|
||||
EXPECT_EQ(0U, segLoad.pAddr);
|
||||
EXPECT_EQ(sizeof(data), segLoad.fileSz);
|
||||
EXPECT_EQ(0U, segLoad.memSz);
|
||||
EXPECT_EQ(8U, segLoad.align);
|
||||
EXPECT_EQ(0, memcmp(data, segLoadBitsData, sizeof(data)));
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSegmentWithoutDataThenOffsetsAreLeftIntact) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
elfEncoder64.appendSegment(PT_LOAD, {});
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfProgramHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.phOff);
|
||||
EXPECT_EQ(1U, header64.phNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto &segLoad = *reinterpret_cast<ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(PT_LOAD, segLoad.type);
|
||||
EXPECT_EQ(PF_NONE, segLoad.flags);
|
||||
EXPECT_EQ(0U, segLoad.offset);
|
||||
EXPECT_EQ(0U, segLoad.vAddr);
|
||||
EXPECT_EQ(0U, segLoad.pAddr);
|
||||
EXPECT_EQ(0U, segLoad.fileSz);
|
||||
EXPECT_EQ(0U, segLoad.memSz);
|
||||
EXPECT_EQ(8U, segLoad.align);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingBothSectionAndSegmentThenProperElfIsEmited) {
|
||||
const uint8_t segmentData[] = "235711131719";
|
||||
const uint8_t sectionData[] = "232931374143";
|
||||
const uint8_t sectionNamesData[] = "\0.shstrtab\0.my_name_is_important";
|
||||
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.type = ET_EXEC;
|
||||
header.entry = 16U;
|
||||
header.phOff = static_cast<decltype(header.phOff)>(sizeof(header));
|
||||
header.shOff = static_cast<decltype(header.shOff)>(sizeof(header) + sizeof(ElfProgramHeader<EI_CLASS_64>));
|
||||
header.flags = 4U;
|
||||
header.phNum = 1U;
|
||||
header.shNum = 3U;
|
||||
header.shStrNdx = 2U;
|
||||
|
||||
ElfProgramHeader<EI_CLASS_64> segment;
|
||||
segment.type = PT_LOAD;
|
||||
segment.flags = PF_R | PF_X;
|
||||
segment.offset = static_cast<decltype(segment.offset)>(header.shOff + sizeof(ElfSectionHeader<EI_CLASS_64>) * 3);
|
||||
segment.vAddr = 4096U;
|
||||
segment.pAddr = 4096U * 16;
|
||||
segment.fileSz = static_cast<decltype(segment.fileSz)>(sizeof(segmentData));
|
||||
segment.memSz = 8192U;
|
||||
segment.align = 8U;
|
||||
|
||||
ElfSectionHeader<EI_CLASS_64> sectionUndef;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionProgBits;
|
||||
sectionProgBits.name = 11U;
|
||||
sectionProgBits.type = SHT_PROGBITS;
|
||||
sectionProgBits.flags = SHF_ALLOC;
|
||||
sectionProgBits.addr = 16U;
|
||||
sectionProgBits.offset = static_cast<decltype(sectionProgBits.offset)>(segment.offset + alignUp(static_cast<size_t>(segment.fileSz), static_cast<size_t>(segment.align)));
|
||||
sectionProgBits.size = static_cast<decltype(sectionProgBits.size)>(sizeof(sectionData));
|
||||
sectionProgBits.link = SHN_UNDEF;
|
||||
sectionProgBits.info = 0U;
|
||||
sectionProgBits.addralign = 16U;
|
||||
sectionProgBits.entsize = 0U;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionSectionNames;
|
||||
sectionSectionNames.name = 1U;
|
||||
sectionSectionNames.type = SHT_STRTAB;
|
||||
sectionSectionNames.flags = SHF_NONE;
|
||||
sectionSectionNames.addr = 0U;
|
||||
sectionSectionNames.offset = static_cast<decltype(sectionSectionNames.offset)>(sectionProgBits.offset + alignUp(static_cast<size_t>(sectionProgBits.size), static_cast<size_t>(sectionProgBits.addralign)));
|
||||
sectionSectionNames.size = static_cast<decltype(sectionSectionNames.size)>(sizeof(sectionNamesData));
|
||||
sectionSectionNames.link = SHN_UNDEF;
|
||||
sectionSectionNames.info = 0U;
|
||||
sectionSectionNames.addralign = 8U;
|
||||
sectionSectionNames.entsize = 0U;
|
||||
|
||||
std::vector<uint8_t> handMade;
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&header), reinterpret_cast<uint8_t *>(&header + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&segment), reinterpret_cast<uint8_t *>(&segment + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionUndef), reinterpret_cast<uint8_t *>(§ionUndef + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionProgBits), reinterpret_cast<uint8_t *>(§ionProgBits + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionSectionNames), reinterpret_cast<uint8_t *>(§ionSectionNames + 1));
|
||||
handMade.insert(handMade.end(), segmentData, segmentData + sizeof(segmentData));
|
||||
handMade.resize(static_cast<size_t>(sectionProgBits.offset), 0U);
|
||||
handMade.insert(handMade.end(), sectionData, sectionData + sizeof(sectionData));
|
||||
handMade.resize(static_cast<size_t>(sectionSectionNames.offset), 0U);
|
||||
handMade.insert(handMade.end(), sectionNamesData, sectionNamesData + sizeof(sectionNamesData));
|
||||
handMade.resize(static_cast<size_t>(sectionSectionNames.offset + alignUp(sizeof(sectionNamesData), 8U)), 0U);
|
||||
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64;
|
||||
{
|
||||
auto &encodedHeader = elfEncoder64.getElfFileHeader();
|
||||
encodedHeader.type = ET_EXEC;
|
||||
encodedHeader.entry = 16U;
|
||||
encodedHeader.flags = 4U;
|
||||
|
||||
auto &encodedSegment = elfEncoder64.appendSegment(PT_LOAD, segmentData);
|
||||
encodedSegment.type = PT_LOAD;
|
||||
encodedSegment.flags = PF_R | PF_X;
|
||||
encodedSegment.vAddr = 4096U;
|
||||
encodedSegment.pAddr = 4096U * 16;
|
||||
encodedSegment.memSz = 8192U;
|
||||
encodedSegment.align = 8U;
|
||||
|
||||
ElfSectionHeader<EI_CLASS_64> encodedSectionProgBits;
|
||||
encodedSectionProgBits.name = elfEncoder64.appendSectionName(".my_name_is_important");
|
||||
encodedSectionProgBits.type = SHT_PROGBITS;
|
||||
encodedSectionProgBits.flags = SHF_ALLOC;
|
||||
encodedSectionProgBits.addr = 16U;
|
||||
encodedSectionProgBits.link = SHN_UNDEF;
|
||||
encodedSectionProgBits.info = 0U;
|
||||
encodedSectionProgBits.addralign = 16U;
|
||||
encodedSectionProgBits.entsize = 0U;
|
||||
|
||||
elfEncoder64.appendSection(encodedSectionProgBits, sectionData);
|
||||
}
|
||||
|
||||
auto generated = elfEncoder64.encode();
|
||||
|
||||
EXPECT_EQ(handMade, generated);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenDefaultAlignmentIsRaisedThenSegmentDataAbideByIt) {
|
||||
const uint8_t segmentData[] = "235711131719";
|
||||
const uint8_t sectionData[] = "232931374143475";
|
||||
|
||||
static constexpr size_t alignment = 128U;
|
||||
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true, alignment);
|
||||
elfEncoder64.appendSegment(PT_LOAD, segmentData);
|
||||
|
||||
elfEncoder64.appendSection(NEO::Elf::SHT_PROGBITS, "my_name_is_important", sectionData);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
auto sectionHeaders = reinterpret_cast<NEO::Elf::ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.shOff));
|
||||
auto programHeaders = reinterpret_cast<NEO::Elf::ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.phOff));
|
||||
for (const auto §ion : NEO::CreateRange(sectionHeaders, header64.shNum)) {
|
||||
EXPECT_EQ(0U, section.offset % 8U);
|
||||
}
|
||||
for (const auto &segment : NEO::CreateRange(programHeaders, header64.phNum)) {
|
||||
EXPECT_EQ(0U, segment.offset % alignment);
|
||||
EXPECT_LE(alignment, segment.align);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenDefaultAlignmentIsLoweredThenSectionAndSegmentDataAbideByIt) {
|
||||
const uint8_t segmentData[] = "235711131719";
|
||||
const uint8_t sectionData[] = "232931374143475";
|
||||
|
||||
static constexpr size_t alignment = 1U;
|
||||
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true, alignment);
|
||||
elfEncoder64.appendSegment(PT_LOAD, segmentData);
|
||||
|
||||
elfEncoder64.appendSection(NEO::Elf::SHT_PROGBITS, "my_name_is_important", sectionData);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
auto sectionHeaders = reinterpret_cast<NEO::Elf::ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.shOff));
|
||||
NEO::Elf::ElfSectionHeader<EI_CLASS_64> *sectionNamesSection = sectionHeaders + header64.shStrNdx;
|
||||
size_t unpaddedSize = sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(NEO::Elf::ElfSectionHeader<EI_CLASS_64>) + sizeof(NEO::Elf::ElfProgramHeader<EI_CLASS_64>);
|
||||
unpaddedSize += sizeof(segmentData) + sizeof(sectionData) + static_cast<size_t>(sectionNamesSection->size);
|
||||
EXPECT_EQ(unpaddedSize, elfData64.size());
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingEmptySectionNameThenAlwaysReturn0AsOffset) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, true);
|
||||
auto offset0 = elfEncoder64.appendSectionName({});
|
||||
auto offset1 = elfEncoder64.appendSectionName({});
|
||||
auto offset2 = elfEncoder64.appendSectionName({});
|
||||
EXPECT_EQ(0U, offset0);
|
||||
EXPECT_EQ(0U, offset1);
|
||||
EXPECT_EQ(0U, offset2);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionNameThenEmplacedStringIsAlwaysNullterminated) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
|
||||
auto strOffset = elfEncoder64.appendSectionName(ConstStringRef("abc", 2));
|
||||
auto strOffset2 = elfEncoder64.appendSectionName(ConstStringRef("de", 3));
|
||||
auto strOffset3 = elfEncoder64.appendSectionName(ConstStringRef("g"));
|
||||
elfEncoder64.appendSection(SHT_NOBITS, "my_name_is_important", {});
|
||||
EXPECT_EQ(strOffset + 3, strOffset2);
|
||||
EXPECT_EQ(strOffset2 + 3, strOffset3);
|
||||
auto elfData = elfEncoder64.encode();
|
||||
auto header = reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData.data());
|
||||
|
||||
auto sectionNamesSection = reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData.data() + static_cast<size_t>(header->shOff + header->shStrNdx * header->shEntSize));
|
||||
EXPECT_STREQ("ab", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset));
|
||||
EXPECT_STREQ("de", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset2));
|
||||
EXPECT_STREQ("g", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset3));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,333 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/device_binary_format/patchtokens_decoder.h"
|
||||
|
||||
#include "igfxfmid.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
extern GFXCORE_FAMILY renderCoreFamily;
|
||||
|
||||
namespace PatchTokensTestData {
|
||||
template <typename TokenT>
|
||||
inline TokenT initToken(iOpenCL::PATCH_TOKEN tok) {
|
||||
TokenT ret = {};
|
||||
ret.Size = sizeof(TokenT);
|
||||
ret.Token = tok;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline iOpenCL::SPatchDataParameterBuffer initDataParameterBufferToken(iOpenCL::DATA_PARAMETER_TOKEN type, uint32_t sourceIndex = 0, uint32_t argNum = 0) {
|
||||
iOpenCL::SPatchDataParameterBuffer tok = {};
|
||||
tok.Size = static_cast<uint32_t>(sizeof(iOpenCL::SPatchDataParameterBuffer));
|
||||
tok.Token = iOpenCL::PATCH_TOKEN_DATA_PARAMETER_BUFFER;
|
||||
tok.Type = type;
|
||||
tok.SourceOffset = sourceIndex * sizeof(uint32_t);
|
||||
tok.ArgumentNumber = argNum;
|
||||
return tok;
|
||||
}
|
||||
|
||||
inline uint32_t pushBackString(const std::string &str, std::vector<uint8_t> &storage) {
|
||||
auto offset = storage.size();
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(str.c_str()), reinterpret_cast<const uint8_t *>(str.c_str()) + str.size());
|
||||
return static_cast<uint32_t>(offset);
|
||||
}
|
||||
|
||||
inline uint32_t pushBackStringToken(const std::string &str, uint32_t stringIndex, std::vector<uint8_t> &outStream) {
|
||||
auto off = outStream.size();
|
||||
outStream.reserve(outStream.size() + sizeof(iOpenCL::SPatchString) + str.length());
|
||||
outStream.resize(outStream.size() + sizeof(iOpenCL::SPatchString));
|
||||
iOpenCL::SPatchString *tok = reinterpret_cast<iOpenCL::SPatchString *>(outStream.data() + off);
|
||||
*tok = initToken<iOpenCL::SPatchString>(iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STRING);
|
||||
tok->StringSize = static_cast<uint32_t>(str.length());
|
||||
tok->Size += tok->StringSize;
|
||||
tok->Index = stringIndex;
|
||||
pushBackString(str, outStream);
|
||||
return static_cast<uint32_t>(off);
|
||||
};
|
||||
|
||||
inline uint32_t pushBackArgInfoToken(std::vector<uint8_t> &outStream,
|
||||
uint32_t argNum = 0,
|
||||
const std::string &addressQualifier = "__global", const std::string &accessQualifier = "read_write",
|
||||
const std::string &argName = "custom_arg", const std::string &typeName = "int*;", std::string typeQualifier = "const") {
|
||||
auto off = outStream.size();
|
||||
iOpenCL::SPatchKernelArgumentInfo tok = {};
|
||||
tok.Token = iOpenCL::PATCH_TOKEN_KERNEL_ARGUMENT_INFO;
|
||||
tok.AddressQualifierSize = static_cast<uint32_t>(addressQualifier.size());
|
||||
tok.AccessQualifierSize = static_cast<uint32_t>(accessQualifier.size());
|
||||
tok.ArgumentNameSize = static_cast<uint32_t>(argName.size());
|
||||
tok.TypeNameSize = static_cast<uint32_t>(typeName.size());
|
||||
tok.TypeQualifierSize = static_cast<uint32_t>(typeQualifier.size());
|
||||
tok.Size = sizeof(iOpenCL::SPatchKernelArgumentInfo) + tok.AddressQualifierSize + tok.AccessQualifierSize + tok.ArgumentNameSize + tok.TypeNameSize + tok.TypeQualifierSize;
|
||||
|
||||
outStream.insert(outStream.end(), reinterpret_cast<const uint8_t *>(&tok), reinterpret_cast<const uint8_t *>(&tok) + sizeof(tok));
|
||||
pushBackString(addressQualifier, outStream);
|
||||
pushBackString(accessQualifier, outStream);
|
||||
pushBackString(argName, outStream);
|
||||
pushBackString(typeName, outStream);
|
||||
pushBackString(typeQualifier, outStream);
|
||||
return static_cast<uint32_t>(off);
|
||||
}
|
||||
|
||||
struct ValidEmptyProgram : NEO::PatchTokenBinary::ProgramFromPatchtokens {
|
||||
ValidEmptyProgram() {
|
||||
iOpenCL::SProgramBinaryHeader headerTok = {};
|
||||
headerTok.Magic = iOpenCL::MAGIC_CL;
|
||||
headerTok.Version = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
headerTok.Device = renderCoreFamily;
|
||||
headerTok.GPUPointerSizeInBytes = sizeof(uintptr_t);
|
||||
this->decodeStatus = NEO::DecodeError::Success;
|
||||
|
||||
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&headerTok), reinterpret_cast<uint8_t *>((&headerTok) + 1));
|
||||
recalcTokPtr();
|
||||
}
|
||||
void recalcTokPtr() {
|
||||
this->blobs.programInfo = storage;
|
||||
this->headerMutable = reinterpret_cast<iOpenCL::SProgramBinaryHeader *>(storage.data());
|
||||
this->header = this->headerMutable;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> storage;
|
||||
iOpenCL::SProgramBinaryHeader *headerMutable = nullptr;
|
||||
};
|
||||
|
||||
struct ValidProgramWithConstantSurface : ValidEmptyProgram {
|
||||
ValidProgramWithConstantSurface() {
|
||||
iOpenCL::SPatchAllocateConstantMemorySurfaceProgramBinaryInfo constSurfTok = {};
|
||||
constSurfTok.Token = iOpenCL::PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
|
||||
constSurfTok.Size = sizeof(constSurfTok);
|
||||
constSurfTok.InlineDataSize = 128;
|
||||
this->programScopeTokens.allocateConstantMemorySurface.push_back(nullptr);
|
||||
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&constSurfTok), reinterpret_cast<uint8_t *>((&constSurfTok) + 1));
|
||||
storage.resize(storage.size() + constSurfTok.InlineDataSize);
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
ValidEmptyProgram::recalcTokPtr();
|
||||
this->constSurfMutable = reinterpret_cast<iOpenCL::SPatchAllocateConstantMemorySurfaceProgramBinaryInfo *>(storage.data() + sizeof(*this->headerMutable));
|
||||
this->programScopeTokens.allocateConstantMemorySurface[0] = this->constSurfMutable;
|
||||
this->blobs.patchList = ArrayRef<const uint8_t>(storage.data() + sizeof(*this->headerMutable), storage.size() - sizeof(*this->headerMutable));
|
||||
this->headerMutable->PatchListSize = static_cast<uint32_t>(this->blobs.patchList.size());
|
||||
}
|
||||
|
||||
iOpenCL::SPatchAllocateConstantMemorySurfaceProgramBinaryInfo *constSurfMutable = nullptr;
|
||||
};
|
||||
|
||||
struct ValidProgramWithGlobalSurface : ValidEmptyProgram {
|
||||
ValidProgramWithGlobalSurface() {
|
||||
iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo globalSurfTok = {};
|
||||
globalSurfTok.Token = iOpenCL::PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
|
||||
globalSurfTok.Size = sizeof(globalSurfTok);
|
||||
globalSurfTok.InlineDataSize = 256;
|
||||
this->programScopeTokens.allocateGlobalMemorySurface.push_back(nullptr);
|
||||
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&globalSurfTok), reinterpret_cast<uint8_t *>((&globalSurfTok) + 1));
|
||||
storage.resize(storage.size() + globalSurfTok.InlineDataSize);
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
ValidEmptyProgram::recalcTokPtr();
|
||||
this->globalSurfMutable = reinterpret_cast<iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *>(storage.data() + sizeof(*this->headerMutable));
|
||||
this->programScopeTokens.allocateGlobalMemorySurface[0] = this->globalSurfMutable;
|
||||
this->blobs.patchList = ArrayRef<const uint8_t>(storage.data() + sizeof(*this->headerMutable), storage.size() - sizeof(*this->headerMutable));
|
||||
this->headerMutable->PatchListSize = static_cast<uint32_t>(this->blobs.patchList.size());
|
||||
}
|
||||
|
||||
iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *globalSurfMutable = nullptr;
|
||||
};
|
||||
|
||||
struct ValidProgramWithConstantSurfaceAndPointer : ValidProgramWithConstantSurface {
|
||||
ValidProgramWithConstantSurfaceAndPointer() {
|
||||
iOpenCL::SPatchConstantPointerProgramBinaryInfo constantPointerTok = {};
|
||||
constantPointerTok.Token = iOpenCL::PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO;
|
||||
constantPointerTok.Size = sizeof(constantPointerTok);
|
||||
constantPointerTok.ConstantBufferIndex = 0;
|
||||
constantPointerTok.BufferIndex = 0;
|
||||
constantPointerTok.BufferType = iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER;
|
||||
constantPointerTok.ConstantPointerOffset = 96;
|
||||
this->programScopeTokens.constantPointer.push_back(nullptr);
|
||||
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&constantPointerTok), reinterpret_cast<uint8_t *>((&constantPointerTok) + 1));
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
ValidProgramWithConstantSurface::recalcTokPtr();
|
||||
this->constantPointerMutable = reinterpret_cast<iOpenCL::SPatchConstantPointerProgramBinaryInfo *>(storage.data() + sizeof(*this->headerMutable) + sizeof(*this->constSurfMutable) + this->constSurfMutable->InlineDataSize);
|
||||
this->programScopeTokens.constantPointer[0] = this->constantPointerMutable;
|
||||
}
|
||||
|
||||
iOpenCL::SPatchConstantPointerProgramBinaryInfo *constantPointerMutable = nullptr;
|
||||
};
|
||||
|
||||
struct ValidProgramWithGlobalSurfaceAndPointer : ValidProgramWithGlobalSurface {
|
||||
ValidProgramWithGlobalSurfaceAndPointer() {
|
||||
iOpenCL::SPatchGlobalPointerProgramBinaryInfo globalPointerTok = {};
|
||||
globalPointerTok.Token = iOpenCL::PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO;
|
||||
globalPointerTok.Size = sizeof(globalPointerTok);
|
||||
globalPointerTok.GlobalBufferIndex = 0;
|
||||
globalPointerTok.BufferIndex = 0;
|
||||
globalPointerTok.BufferType = iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER;
|
||||
globalPointerTok.GlobalPointerOffset = 48;
|
||||
this->programScopeTokens.globalPointer.push_back(nullptr);
|
||||
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&globalPointerTok), reinterpret_cast<uint8_t *>((&globalPointerTok) + 1));
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
ValidProgramWithGlobalSurface::recalcTokPtr();
|
||||
this->globalPointerMutable = reinterpret_cast<iOpenCL::SPatchGlobalPointerProgramBinaryInfo *>(storage.data() + sizeof(*this->headerMutable) + sizeof(*this->globalSurfMutable) + this->globalSurfMutable->InlineDataSize);
|
||||
this->programScopeTokens.globalPointer[0] = this->globalPointerMutable;
|
||||
}
|
||||
|
||||
iOpenCL::SPatchGlobalPointerProgramBinaryInfo *globalPointerMutable = nullptr;
|
||||
};
|
||||
|
||||
struct ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers : ValidProgramWithConstantSurfaceAndPointer {
|
||||
ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers() {
|
||||
globalVariableTokensOffset = this->storage.size();
|
||||
this->constantPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER;
|
||||
|
||||
ValidProgramWithGlobalSurfaceAndPointer globalVarSurfProg;
|
||||
this->programScopeTokens.globalPointer.push_back(nullptr);
|
||||
this->programScopeTokens.allocateGlobalMemorySurface.push_back(nullptr);
|
||||
this->storage.insert(this->storage.end(), globalVarSurfProg.storage.data() + sizeof(*globalVarSurfProg.headerMutable),
|
||||
globalVarSurfProg.storage.data() + globalVarSurfProg.storage.size());
|
||||
recalcTokPtr();
|
||||
this->globalPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER;
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
this->ValidProgramWithConstantSurfaceAndPointer::recalcTokPtr();
|
||||
this->globalSurfMutable = reinterpret_cast<iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *>(storage.data() + globalVariableTokensOffset);
|
||||
this->programScopeTokens.allocateGlobalMemorySurface[0] = this->globalSurfMutable;
|
||||
this->blobs.patchList = ArrayRef<const uint8_t>(storage.data() + sizeof(*this->headerMutable), storage.size() - sizeof(*this->headerMutable));
|
||||
this->headerMutable->PatchListSize = static_cast<uint32_t>(this->blobs.patchList.size());
|
||||
|
||||
this->globalPointerMutable = reinterpret_cast<iOpenCL::SPatchGlobalPointerProgramBinaryInfo *>(storage.data() + globalVariableTokensOffset + sizeof(*this->globalSurfMutable) + this->globalSurfMutable->InlineDataSize);
|
||||
this->programScopeTokens.globalPointer[0] = this->globalPointerMutable;
|
||||
}
|
||||
|
||||
size_t globalVariableTokensOffset = 0U;
|
||||
iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *globalSurfMutable = nullptr;
|
||||
iOpenCL::SPatchGlobalPointerProgramBinaryInfo *globalPointerMutable = nullptr;
|
||||
};
|
||||
|
||||
struct ValidEmptyKernel {
|
||||
static NEO::PatchTokenBinary::KernelFromPatchtokens create(std::vector<uint8_t> &storage) {
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens ret;
|
||||
iOpenCL::SKernelBinaryHeaderCommon headerTokInl = {};
|
||||
auto execEnvTokInl = initToken<iOpenCL::SPatchExecutionEnvironment>(iOpenCL::PATCH_TOKEN_EXECUTION_ENVIRONMENT);
|
||||
execEnvTokInl.LargestCompiledSIMDSize = 32U;
|
||||
execEnvTokInl.CompiledSIMD32 = 1U;
|
||||
headerTokInl.PatchListSize = sizeof(execEnvTokInl);
|
||||
ret.decodeStatus = NEO::DecodeError::Success;
|
||||
ret.name = "test_kernel";
|
||||
headerTokInl.KernelNameSize = static_cast<uint32_t>(ret.name.size());
|
||||
|
||||
auto kernOffset = storage.size();
|
||||
storage.reserve(storage.size() + 512);
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&headerTokInl), reinterpret_cast<const uint8_t *>((&headerTokInl) + 1));
|
||||
auto headerTok = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(&*(storage.begin() + kernOffset));
|
||||
ret.NEO::PatchTokenBinary::KernelFromPatchtokens::header = headerTok;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(ret.name.begin()), reinterpret_cast<const uint8_t *>(ret.name.end()));
|
||||
auto execEnvOffset = storage.size();
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&execEnvTokInl), reinterpret_cast<const uint8_t *>((&execEnvTokInl) + 1));
|
||||
ret.blobs.kernelInfo = ArrayRef<const uint8_t>(storage.data() + kernOffset, storage.data() + kernOffset + storage.size());
|
||||
headerTok->CheckSum = NEO::PatchTokenBinary::calcKernelChecksum(ret.blobs.kernelInfo);
|
||||
ret.blobs.patchList = ArrayRef<const uint8_t>(storage.data() + execEnvOffset, storage.data() + storage.size());
|
||||
ret.tokens.executionEnvironment = reinterpret_cast<iOpenCL::SPatchExecutionEnvironment *>(storage.data() + execEnvOffset);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct ValidProgramWithKernel : ValidEmptyProgram {
|
||||
ValidProgramWithKernel() {
|
||||
this->headerMutable->NumberOfKernels = 1;
|
||||
kernOffset = storage.size();
|
||||
this->kernels.push_back(ValidEmptyKernel::create(storage));
|
||||
this->kernels[0].decodeStatus = NEO::DecodeError::Success;
|
||||
kernExecEnvOffset = ptrDiff(this->kernels[0].blobs.patchList.begin(), storage.data());
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
ValidEmptyProgram::recalcTokPtr();
|
||||
this->kernels[0].blobs.kernelInfo = ArrayRef<const uint8_t>(storage.data() + kernOffset, storage.data() + storage.size());
|
||||
kernelHeaderMutable = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(&*(storage.begin() + kernOffset));
|
||||
this->kernels[0].header = kernelHeaderMutable;
|
||||
char *name = reinterpret_cast<char *>(storage.data() + kernOffset + sizeof(iOpenCL::SKernelBinaryHeaderCommon));
|
||||
this->kernels[0].name = ArrayRef<const char>(name, name + kernelHeaderMutable->KernelNameSize);
|
||||
kernelExecEnvMutable = reinterpret_cast<iOpenCL::SPatchExecutionEnvironment *>(&*(storage.begin() + kernExecEnvOffset));
|
||||
this->kernels[0].tokens.executionEnvironment = kernelExecEnvMutable;
|
||||
|
||||
this->kernels[0].blobs.patchList = ArrayRef<const uint8_t>(storage.data() + kernExecEnvOffset, storage.data() + storage.size());
|
||||
this->kernelHeaderMutable->PatchListSize = static_cast<uint32_t>(this->kernels[0].blobs.patchList.size());
|
||||
kernelHeaderMutable->CheckSum = NEO::PatchTokenBinary::calcKernelChecksum(this->kernels[0].blobs.kernelInfo);
|
||||
}
|
||||
|
||||
size_t kernOffset = 0U;
|
||||
size_t kernExecEnvOffset = 0U;
|
||||
iOpenCL::SKernelBinaryHeaderCommon *kernelHeaderMutable = nullptr;
|
||||
iOpenCL::SPatchExecutionEnvironment *kernelExecEnvMutable = nullptr;
|
||||
};
|
||||
|
||||
struct ValidProgramWithKernelUsingSlm : ValidProgramWithKernel {
|
||||
ValidProgramWithKernelUsingSlm() {
|
||||
slmMutableOffset = storage.size();
|
||||
iOpenCL::SPatchAllocateLocalSurface slmTok = {};
|
||||
slmTok.Token = iOpenCL::PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE;
|
||||
slmTok.Size = sizeof(slmTok);
|
||||
slmTok.TotalInlineLocalMemorySize = 16;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&slmTok), reinterpret_cast<const uint8_t *>((&slmTok) + 1));
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
ValidProgramWithKernel::recalcTokPtr();
|
||||
slmMutable = reinterpret_cast<iOpenCL::SPatchAllocateLocalSurface *>(storage.data() + slmMutableOffset);
|
||||
this->kernels[0].tokens.allocateLocalSurface = slmMutable;
|
||||
}
|
||||
|
||||
iOpenCL::SPatchAllocateLocalSurface *slmMutable = nullptr;
|
||||
size_t slmMutableOffset = 0U;
|
||||
};
|
||||
|
||||
struct ValidProgramWithKernelAndArg : ValidProgramWithKernel {
|
||||
ValidProgramWithKernelAndArg() {
|
||||
kernelArgOffset = storage.size();
|
||||
|
||||
pushBackArgInfoToken(storage);
|
||||
this->kernels[0].tokens.kernelArgs.resize(1);
|
||||
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
void recalcTokPtr() {
|
||||
ValidProgramWithKernel::recalcTokPtr();
|
||||
arg0InfoMutable = reinterpret_cast<iOpenCL::SPatchKernelArgumentInfo *>(storage.data() + kernelArgOffset);
|
||||
this->kernels[0].tokens.kernelArgs[0].argInfo = arg0InfoMutable;
|
||||
arg0InfoAddressQualifierMutable = reinterpret_cast<char *>(arg0InfoMutable + 1);
|
||||
arg0InfoAccessQualifierMutable = arg0InfoAddressQualifierMutable + arg0InfoMutable->AddressQualifierSize;
|
||||
arg0NameMutable = arg0InfoAccessQualifierMutable + arg0InfoMutable->AccessQualifierSize;
|
||||
arg0TypeMutable = arg0NameMutable + arg0InfoMutable->ArgumentNameSize;
|
||||
arg0TypeQualifierMutable = arg0TypeMutable + arg0InfoMutable->TypeNameSize;
|
||||
}
|
||||
|
||||
iOpenCL::SPatchKernelArgumentInfo *arg0InfoMutable = nullptr;
|
||||
char *arg0InfoAddressQualifierMutable = nullptr;
|
||||
char *arg0InfoAccessQualifierMutable = nullptr;
|
||||
char *arg0NameMutable = nullptr;
|
||||
char *arg0TypeMutable = nullptr;
|
||||
char *arg0TypeQualifierMutable = nullptr;
|
||||
size_t kernelArgOffset = 0U;
|
||||
};
|
||||
|
||||
} // namespace PatchTokensTestData
|
||||
@@ -1,524 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/patchtokens_decoder.h"
|
||||
#include "shared/source/device_binary_format/patchtokens_validator.h"
|
||||
#include "device_binary_format/patchtokens_tests.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidOrUnknownStatusThenValidationFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.decodeStatus = NEO::DecodeError::Undefined;
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
warning.clear();
|
||||
|
||||
prog.decodeStatus = NEO::DecodeError::InvalidBinary;
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithASingleConstantSurfaceThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurface prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithMultipleConstantSurfacesThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurface prog;
|
||||
std::string error, warning;
|
||||
|
||||
iOpenCL::SPatchAllocateConstantMemorySurfaceProgramBinaryInfo constSurface2 = *prog.programScopeTokens.allocateConstantMemorySurface[0];
|
||||
prog.programScopeTokens.allocateConstantMemorySurface.push_back(&constSurface2);
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled number of global constants surfaces > 1", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithASingleGlobalSurfaceThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurface prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithMultipleGlobalSurfacesThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurface prog;
|
||||
std::string error, warning;
|
||||
|
||||
iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo globSurface2 = *prog.programScopeTokens.allocateGlobalMemorySurface[0];
|
||||
prog.programScopeTokens.allocateGlobalMemorySurface.push_back(&globSurface2);
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled number of global variables surfaces > 1", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithValidConstantPointerThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferIndexThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->BufferIndex = 1;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidGpuPointerSizeThenValidationFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 0U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Invalid pointer size", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 1U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 2U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 3U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 4U;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 5U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 6U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 7U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 8U;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 9U;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerConstantBufferIndexThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->ConstantBufferIndex = 1;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferTypeThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerOffsetThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->ConstantPointerOffset = prog.constSurfMutable->InlineDataSize;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithoutConstantSurfaceButWithConstantPointerThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.programScopeTokens.allocateConstantMemorySurface.clear();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithValidGlobalPointerThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithMixedGlobalVarAndConstSurfacesAndPointersThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenInvalidProgramWithMixedGlobalVarAndConstSurfacesAndPointersThenValidationFails) {
|
||||
std::string error, warning;
|
||||
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer progGlobalVar;
|
||||
progGlobalVar.globalPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(progGlobalVar, error, warning));
|
||||
EXPECT_FALSE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer progConstVar;
|
||||
progConstVar.constantPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(progConstVar, error, warning));
|
||||
EXPECT_FALSE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferIndexThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->BufferIndex = 1;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerGlobalBufferIndexThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->GlobalBufferIndex = 1;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferTypeThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerOffsetThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->GlobalPointerOffset = prog.globalSurfMutable->InlineDataSize;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithoutGlobalSurfaceButWithGlobalPointerThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.programScopeTokens.allocateGlobalMemorySurface.clear();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownTokenCantBeSkippedThenValidationFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.unhandledTokens.push_back(&unknownToken);
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = false;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedError = "Unhandled required program-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_STREQ(expectedError.c_str(), error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownTokenCanBeSkippedThenValidationSucceedsAndEmitsWarning) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.unhandledTokens.push_back(&unknownToken);
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = true;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedWarning = "Unknown program-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithUnsupportedPatchTokenVersionThenValidationFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.headerMutable->Version = std::numeric_limits<uint32_t>::max();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Unhandled Version of Patchtokens: expected: " + std::to_string(iOpenCL::CURRENT_ICBE_VERSION) + ", got: " + std::to_string(prog.header->Version);
|
||||
EXPECT_STREQ(expectedError.c_str(), error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithKernelThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidOrUnknownStatusThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.kernels[0].decodeStatus = NEO::DecodeError::Undefined;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
warning.clear();
|
||||
|
||||
prog.kernels[0].decodeStatus = NEO::DecodeError::InvalidBinary;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidChecksumThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.kernelHeaderMutable->CheckSum += 1;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("KernelFromPatchtokens has invalid checksum", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithKernelUsingSlmThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithKernelUsingSlm prog;
|
||||
std::string error, warning;
|
||||
|
||||
//size_t slmSizeAvailable = 1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchTokenWhenUknownTokenCantBeSkippedThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.kernels[0].unhandledTokens.push_back(&unknownToken);
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = false;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedError = "Unhandled required kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_STREQ(expectedError.c_str(), error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchTokenWhenUknownTokenCanBeSkippedThenValidationSucceedsAndEmitsWarning) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.kernels[0].unhandledTokens.push_back(&unknownToken);
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = true;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedWarning = "Unknown kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelArgsHasProperQualifiersThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithKernelAndArgThenKernelArgInfoIsOptional) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
|
||||
std::string error, warning;
|
||||
prog.kernels[0].tokens.kernelArgs[0].argInfo = nullptr;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAddressSpaceThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
|
||||
std::string error, warning;
|
||||
prog.arg0InfoAddressQualifierMutable[2] = '\0';
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Unhandled address qualifier";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAccessQualifierThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
|
||||
std::string error, warning;
|
||||
prog.arg0InfoAccessQualifierMutable[2] = '\0';
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Unhandled access qualifier";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentIsMissingThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
prog.kernels[0].tokens.executionEnvironment = nullptr;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Missing execution environment";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentHasInvalidSimdSizeThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 0U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Invalid LargestCompiledSIMDSize";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 1U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 2U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 3U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 4U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 5U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 6U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 7U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 8U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 9U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 16U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 32U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenDefaultStateThenUnhandledPatchtokensAreAllowed) {
|
||||
EXPECT_TRUE(NEO::PatchTokenBinary::allowUnhandledTokens);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_DIRECT_SUBMISSION_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/direct_submission_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_DIRECT_SUBMISSION_TESTS ${NEO_CORE_DIRECT_SUBMISSION_TESTS})
|
||||
|
||||
add_subdirectories()
|
||||
@@ -1,620 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/submissions_aggregator.h"
|
||||
#include "shared/source/debug_settings/debug_settings_manager.h"
|
||||
#include "shared/source/direct_submission/dispatchers/render_dispatcher.h"
|
||||
#include "shared/source/helpers/flush_stamp.h"
|
||||
#include "shared/source/os_interface/os_context.h"
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "helpers/ult_hw_config.h"
|
||||
#include "mocks/mock_direct_submission_hw.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/helpers/dispatch_flags_helper.h"
|
||||
#include "opencl/test/unit_test/helpers/variable_backup.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_csr.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
extern std::atomic<uintptr_t> lastClFlushedPtr;
|
||||
|
||||
struct DirectSubmissionFixture : public DeviceFixture {
|
||||
void SetUp() {
|
||||
DeviceFixture::SetUp();
|
||||
|
||||
osContext.reset(OsContext::create(nullptr, 0u, 0u, aub_stream::ENGINE_RCS, PreemptionMode::ThreadGroup, false));
|
||||
}
|
||||
|
||||
std::unique_ptr<OsContext> osContext;
|
||||
};
|
||||
|
||||
using DirectSubmissionTest = Test<DirectSubmissionFixture>;
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, whenDebugCacheFlushDisabledSetThenExpectNoCpuCacheFlush) {
|
||||
DebugManagerStateRestore restore;
|
||||
DebugManager.flags.DirectSubmissionDisableCpuCacheFlush.set(1);
|
||||
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
EXPECT_TRUE(directSubmission.disableCpuCacheFlush);
|
||||
|
||||
uintptr_t expectedPtrVal = 0;
|
||||
lastClFlushedPtr = 0;
|
||||
void *ptr = reinterpret_cast<void *>(0xABCD00u);
|
||||
size_t size = 64;
|
||||
directSubmission.cpuCachelineFlush(ptr, size);
|
||||
EXPECT_EQ(expectedPtrVal, lastClFlushedPtr);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, whenDebugCacheFlushDisabledNotSetThenExpectCpuCacheFlush) {
|
||||
DebugManagerStateRestore restore;
|
||||
DebugManager.flags.DirectSubmissionDisableCpuCacheFlush.set(0);
|
||||
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
EXPECT_FALSE(directSubmission.disableCpuCacheFlush);
|
||||
|
||||
uintptr_t expectedPtrVal = 0xABCD00u;
|
||||
lastClFlushedPtr = 0;
|
||||
void *ptr = reinterpret_cast<void *>(expectedPtrVal);
|
||||
size_t size = 64;
|
||||
directSubmission.cpuCachelineFlush(ptr, size);
|
||||
EXPECT_EQ(expectedPtrVal, lastClFlushedPtr);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionInitializedWhenRingIsStartedThenExpectAllocationsCreatedAndCommandsDispatched) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
EXPECT_FALSE(directSubmission.disableCpuCacheFlush);
|
||||
|
||||
bool ret = directSubmission.initialize(true);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_TRUE(directSubmission.ringStart);
|
||||
|
||||
EXPECT_NE(nullptr, directSubmission.ringBuffer);
|
||||
EXPECT_NE(nullptr, directSubmission.ringBuffer2);
|
||||
EXPECT_NE(nullptr, directSubmission.semaphores);
|
||||
|
||||
EXPECT_NE(0u, directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionInitializedWhenRingIsNotStartedThenExpectAllocationsCreatedAndCommandsNotDispatched) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_FALSE(directSubmission.ringStart);
|
||||
|
||||
EXPECT_NE(nullptr, directSubmission.ringBuffer);
|
||||
EXPECT_NE(nullptr, directSubmission.ringBuffer2);
|
||||
EXPECT_NE(nullptr, directSubmission.semaphores);
|
||||
|
||||
EXPECT_EQ(0u, directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionSwitchBuffersWhenCurrentIsPrimaryThenExpectNextSecondary) {
|
||||
using RingBufferUse = typename MockDirectSubmissionHw<FamilyType>::RingBufferUse;
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_EQ(RingBufferUse::FirstBuffer, directSubmission.currentRingBuffer);
|
||||
|
||||
GraphicsAllocation *nextRing = directSubmission.switchRingBuffersAllocations();
|
||||
EXPECT_EQ(directSubmission.ringBuffer2, nextRing);
|
||||
EXPECT_EQ(RingBufferUse::SecondBuffer, directSubmission.currentRingBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionSwitchBuffersWhenCurrentIsSecondaryThenExpectNextPrimary) {
|
||||
using RingBufferUse = typename MockDirectSubmissionHw<FamilyType>::RingBufferUse;
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_EQ(RingBufferUse::FirstBuffer, directSubmission.currentRingBuffer);
|
||||
|
||||
GraphicsAllocation *nextRing = directSubmission.switchRingBuffersAllocations();
|
||||
EXPECT_EQ(directSubmission.ringBuffer2, nextRing);
|
||||
EXPECT_EQ(RingBufferUse::SecondBuffer, directSubmission.currentRingBuffer);
|
||||
|
||||
nextRing = directSubmission.switchRingBuffersAllocations();
|
||||
EXPECT_EQ(directSubmission.ringBuffer, nextRing);
|
||||
EXPECT_EQ(RingBufferUse::FirstBuffer, directSubmission.currentRingBuffer);
|
||||
}
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionAllocateFailWhenRingIsStartedThenExpectRingNotStarted) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
EXPECT_FALSE(directSubmission.disableCpuCacheFlush);
|
||||
|
||||
directSubmission.allocateOsResourcesReturn = false;
|
||||
bool ret = directSubmission.initialize(true);
|
||||
EXPECT_FALSE(ret);
|
||||
EXPECT_FALSE(directSubmission.ringStart);
|
||||
|
||||
EXPECT_EQ(0u, directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionSubmitFailWhenRingIsStartedThenExpectRingNotStartedCommandsDispatched) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
directSubmission.submitReturn = false;
|
||||
bool ret = directSubmission.initialize(true);
|
||||
EXPECT_FALSE(ret);
|
||||
EXPECT_FALSE(directSubmission.ringStart);
|
||||
|
||||
EXPECT_NE(0u, directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionStartWhenRingIsStartedThenExpectNoStartCommandsDispatched) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(true);
|
||||
EXPECT_TRUE(ret);
|
||||
size_t usedSize = directSubmission.ringCommandStream.getUsed();
|
||||
|
||||
ret = directSubmission.startRingBuffer();
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_EQ(usedSize, directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionStartWhenRingIsNotStartedThenExpectStartCommandsDispatched) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
size_t usedSize = directSubmission.ringCommandStream.getUsed();
|
||||
|
||||
ret = directSubmission.startRingBuffer();
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_TRUE(directSubmission.ringStart);
|
||||
EXPECT_NE(usedSize, directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionStartWhenRingIsNotStartedSubmitFailThenExpectStartCommandsDispatchedRingNotStarted) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
size_t usedSize = directSubmission.ringCommandStream.getUsed();
|
||||
|
||||
directSubmission.submitReturn = false;
|
||||
ret = directSubmission.startRingBuffer();
|
||||
EXPECT_FALSE(ret);
|
||||
EXPECT_FALSE(directSubmission.ringStart);
|
||||
EXPECT_NE(usedSize, directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionStartWhenRingIsNotStartedAndSwitchBufferIsNeededThenExpectRingAllocationChangedStartCommandsDispatched) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
auto expectedRingBuffer = directSubmission.currentRingBuffer;
|
||||
GraphicsAllocation *oldRingBuffer = directSubmission.ringCommandStream.getGraphicsAllocation();
|
||||
|
||||
directSubmission.ringCommandStream.getSpace(directSubmission.ringCommandStream.getAvailableSpace() - directSubmission.getSizeSemaphoreSection());
|
||||
|
||||
ret = directSubmission.startRingBuffer();
|
||||
auto actualRingBuffer = directSubmission.currentRingBuffer;
|
||||
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_TRUE(directSubmission.ringStart);
|
||||
EXPECT_NE(oldRingBuffer, directSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
EXPECT_EQ(directSubmission.getSizeSemaphoreSection(), directSubmission.ringCommandStream.getUsed());
|
||||
|
||||
EXPECT_NE(expectedRingBuffer, actualRingBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionStopWhenStopRingIsCalledThenExpectStopCommandDispatched) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(true);
|
||||
EXPECT_TRUE(ret);
|
||||
size_t alreadyDispatchedSize = directSubmission.ringCommandStream.getUsed();
|
||||
uint32_t oldQueueCount = directSubmission.semaphoreData->QueueWorkCount;
|
||||
|
||||
directSubmission.stopRingBuffer();
|
||||
size_t expectedDispatchSize = alreadyDispatchedSize + directSubmission.getSizeEnd();
|
||||
EXPECT_EQ(expectedDispatchSize, directSubmission.ringCommandStream.getUsed());
|
||||
EXPECT_EQ(oldQueueCount + 1, directSubmission.semaphoreData->QueueWorkCount);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenDispatchSemaphoreThenExpectCorrectSizeUsed) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
directSubmission.dispatchSemaphoreSection(1u);
|
||||
EXPECT_EQ(directSubmission.getSizeSemaphoreSection(), directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenDispatchStartSectionThenExpectCorrectSizeUsed) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
directSubmission.dispatchStartSection(1ull);
|
||||
EXPECT_EQ(directSubmission.getSizeStartSection(), directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenDispatchSwitchRingBufferSectionThenExpectCorrectSizeUsed) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
directSubmission.dispatchSwitchRingBufferSection(1ull);
|
||||
EXPECT_EQ(directSubmission.getSizeSwitchRingBufferSection(), directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenDispatchFlushSectionThenExpectCorrectSizeUsed) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
directSubmission.dispatchFlushSection();
|
||||
EXPECT_EQ(directSubmission.getSizeFlushSection(), directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenDispatchTagUpdateSectionThenExpectCorrectSizeUsed) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
directSubmission.dispatchTagUpdateSection(0ull, 0ull);
|
||||
EXPECT_EQ(directSubmission.getSizeTagUpdateSection(), directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenDispatchEndingSectionThenExpectCorrectSizeUsed) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
directSubmission.dispatchEndingSection();
|
||||
EXPECT_EQ(directSubmission.getSizeEndingSection(), directSubmission.ringCommandStream.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenGetDispatchSizeThenExpectCorrectSizeReturned) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
size_t expectedSize = directSubmission.getSizeStartSection() +
|
||||
directSubmission.getSizeFlushSection() +
|
||||
directSubmission.getSizeTagUpdateSection() +
|
||||
directSubmission.getSizeSemaphoreSection();
|
||||
size_t actualSize = directSubmission.getSizeDispatch();
|
||||
EXPECT_EQ(expectedSize, actualSize);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenGetEndSizeThenExpectCorrectSizeReturned) {
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
size_t expectedSize = directSubmission.getSizeEndingSection() +
|
||||
directSubmission.getSizeFlushSection();
|
||||
size_t actualSize = directSubmission.getSizeEnd();
|
||||
EXPECT_EQ(expectedSize, actualSize);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionWhenSettingAddressInReturnCommandThenVerifyCorrectlySet) {
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
uint64_t returnAddress = 0x1A2BF000;
|
||||
void *space = directSubmission.ringCommandStream.getSpace(sizeof(MI_BATCH_BUFFER_START));
|
||||
directSubmission.setReturnAddress(space, returnAddress);
|
||||
MI_BATCH_BUFFER_START *bbStart = reinterpret_cast<MI_BATCH_BUFFER_START *>(space);
|
||||
EXPECT_EQ(returnAddress, bbStart->getBatchBufferStartAddressGraphicsaddress472());
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, whenDirectSubmissionInitializedThenExpectCreatedAllocationsFreed) {
|
||||
MemoryManager *memoryManager = pDevice->getExecutionEnvironment()->memoryManager.get();
|
||||
|
||||
std::unique_ptr<MockDirectSubmissionHw<FamilyType>> directSubmission =
|
||||
std::make_unique<MockDirectSubmissionHw<FamilyType>>(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
directSubmission->initialize(false);
|
||||
|
||||
GraphicsAllocation *nulledAllocation = directSubmission->ringBuffer;
|
||||
directSubmission->ringBuffer = nullptr;
|
||||
directSubmission.reset(nullptr);
|
||||
memoryManager->freeGraphicsMemory(nulledAllocation);
|
||||
|
||||
directSubmission =
|
||||
std::make_unique<MockDirectSubmissionHw<FamilyType>>(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
directSubmission->initialize(false);
|
||||
|
||||
nulledAllocation = directSubmission->ringBuffer2;
|
||||
directSubmission->ringBuffer2 = nullptr;
|
||||
directSubmission.reset(nullptr);
|
||||
memoryManager->freeGraphicsMemory(nulledAllocation);
|
||||
|
||||
directSubmission =
|
||||
std::make_unique<MockDirectSubmissionHw<FamilyType>>(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
directSubmission->initialize(false);
|
||||
|
||||
nulledAllocation = directSubmission->semaphores;
|
||||
directSubmission->semaphores = nullptr;
|
||||
directSubmission.reset(nullptr);
|
||||
memoryManager->freeGraphicsMemory(nulledAllocation);
|
||||
}
|
||||
|
||||
struct DirectSubmissionDispatchBufferFixture : public DirectSubmissionFixture {
|
||||
void SetUp() {
|
||||
DirectSubmissionFixture::SetUp();
|
||||
MemoryManager *memoryManager = pDevice->getExecutionEnvironment()->memoryManager.get();
|
||||
const AllocationProperties commandBufferProperties{pDevice->getRootDeviceIndex(),
|
||||
true, 0x1000,
|
||||
GraphicsAllocation::AllocationType::COMMAND_BUFFER,
|
||||
false};
|
||||
commandBuffer = memoryManager->allocateGraphicsMemoryWithProperties(commandBufferProperties);
|
||||
|
||||
batchBuffer.endCmdPtr = &bbStart[0];
|
||||
batchBuffer.commandBufferAllocation = commandBuffer;
|
||||
batchBuffer.usedSize = 0x40;
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
MemoryManager *memoryManager = pDevice->getExecutionEnvironment()->memoryManager.get();
|
||||
memoryManager->freeGraphicsMemory(commandBuffer);
|
||||
|
||||
DirectSubmissionFixture::TearDown();
|
||||
}
|
||||
|
||||
BatchBuffer batchBuffer;
|
||||
uint8_t bbStart[64];
|
||||
GraphicsAllocation *commandBuffer;
|
||||
};
|
||||
|
||||
using DirectSubmissionDispatchBufferTest = Test<DirectSubmissionDispatchBufferFixture>;
|
||||
|
||||
HWTEST_F(DirectSubmissionDispatchBufferTest,
|
||||
givenDirectSubmissionRingStartAndSwitchBuffersWhenDispatchingCommandBufferThenExpectDispatchInCommandBufferAndQueueCountIncrease) {
|
||||
FlushStampTracker flushStamp(true);
|
||||
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(true);
|
||||
EXPECT_TRUE(ret);
|
||||
GraphicsAllocation *oldRingAllocation = directSubmission.ringCommandStream.getGraphicsAllocation();
|
||||
|
||||
EXPECT_EQ(0u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.submitCount);
|
||||
size_t submitSize = directSubmission.cmdDispatcher->getSizePreemption() +
|
||||
directSubmission.getSizeSemaphoreSection();
|
||||
EXPECT_EQ(submitSize, directSubmission.submitSize);
|
||||
EXPECT_EQ(oldRingAllocation->getGpuAddress(), directSubmission.submitGpuAddress);
|
||||
EXPECT_EQ(1u, directSubmission.handleResidencyCount);
|
||||
|
||||
size_t sizeUsed = directSubmission.ringCommandStream.getUsed();
|
||||
ret = directSubmission.dispatchCommandBuffer(batchBuffer, flushStamp);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_EQ(oldRingAllocation, directSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
EXPECT_EQ(1u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(2u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.submitCount);
|
||||
EXPECT_EQ(2u, directSubmission.handleResidencyCount);
|
||||
|
||||
EXPECT_EQ(sizeUsed + directSubmission.getSizeDispatch(), directSubmission.ringCommandStream.getUsed());
|
||||
EXPECT_TRUE(directSubmission.ringStart);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionDispatchBufferTest,
|
||||
givenDirectSubmissionRingNotStartAndSwitchBuffersWhenDispatchingCommandBufferThenExpectDispatchInCommandBufferQueueCountIncreaseAndSubmitToGpu) {
|
||||
FlushStampTracker flushStamp(true);
|
||||
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
GraphicsAllocation *oldRingAllocation = directSubmission.ringCommandStream.getGraphicsAllocation();
|
||||
|
||||
EXPECT_EQ(0u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(0u, directSubmission.submitCount);
|
||||
EXPECT_EQ(1u, directSubmission.handleResidencyCount);
|
||||
|
||||
ret = directSubmission.dispatchCommandBuffer(batchBuffer, flushStamp);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_EQ(oldRingAllocation, directSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
EXPECT_EQ(1u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(2u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.submitCount);
|
||||
size_t submitSize = directSubmission.getSizeDispatch();
|
||||
EXPECT_EQ(submitSize, directSubmission.submitSize);
|
||||
EXPECT_EQ(oldRingAllocation->getGpuAddress(), directSubmission.submitGpuAddress);
|
||||
EXPECT_EQ(1u, directSubmission.handleResidencyCount);
|
||||
|
||||
EXPECT_EQ(directSubmission.getSizeDispatch(), directSubmission.ringCommandStream.getUsed());
|
||||
EXPECT_TRUE(directSubmission.ringStart);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionDispatchBufferTest,
|
||||
givenDirectSubmissionRingStartWhenDispatchingCommandBufferThenExpectDispatchInCommandBufferAndQueueCountIncrease) {
|
||||
FlushStampTracker flushStamp(true);
|
||||
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(true);
|
||||
EXPECT_TRUE(ret);
|
||||
GraphicsAllocation *oldRingAllocation = directSubmission.ringCommandStream.getGraphicsAllocation();
|
||||
|
||||
EXPECT_EQ(0u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.submitCount);
|
||||
size_t submitSize = directSubmission.cmdDispatcher->getSizePreemption() +
|
||||
directSubmission.getSizeSemaphoreSection();
|
||||
EXPECT_EQ(submitSize, directSubmission.submitSize);
|
||||
EXPECT_EQ(oldRingAllocation->getGpuAddress(), directSubmission.submitGpuAddress);
|
||||
EXPECT_EQ(1u, directSubmission.handleResidencyCount);
|
||||
|
||||
directSubmission.ringCommandStream.getSpace(directSubmission.ringCommandStream.getAvailableSpace() -
|
||||
directSubmission.getSizeSwitchRingBufferSection());
|
||||
|
||||
ret = directSubmission.dispatchCommandBuffer(batchBuffer, flushStamp);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_NE(oldRingAllocation, directSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
EXPECT_EQ(1u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(2u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.submitCount);
|
||||
EXPECT_EQ(2u, directSubmission.handleResidencyCount);
|
||||
|
||||
EXPECT_EQ(directSubmission.getSizeDispatch(), directSubmission.ringCommandStream.getUsed());
|
||||
EXPECT_TRUE(directSubmission.ringStart);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionDispatchBufferTest,
|
||||
givenDirectSubmissionRingNotStartWhenDispatchingCommandBufferThenExpectDispatchInCommandBufferQueueCountIncreaseAndSubmitToGpu) {
|
||||
FlushStampTracker flushStamp(true);
|
||||
|
||||
MockDirectSubmissionHw<FamilyType> directSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = directSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_EQ(0u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(0u, directSubmission.submitCount);
|
||||
EXPECT_EQ(1u, directSubmission.handleResidencyCount);
|
||||
|
||||
GraphicsAllocation *oldRingAllocation = directSubmission.ringCommandStream.getGraphicsAllocation();
|
||||
directSubmission.ringCommandStream.getSpace(directSubmission.ringCommandStream.getAvailableSpace() -
|
||||
directSubmission.getSizeSwitchRingBufferSection());
|
||||
uint64_t submitGpuVa = oldRingAllocation->getGpuAddress() + directSubmission.ringCommandStream.getUsed();
|
||||
|
||||
ret = directSubmission.dispatchCommandBuffer(batchBuffer, flushStamp);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_NE(oldRingAllocation, directSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
EXPECT_EQ(1u, directSubmission.semaphoreData->QueueWorkCount);
|
||||
EXPECT_EQ(2u, directSubmission.currentQueueWorkCount);
|
||||
EXPECT_EQ(1u, directSubmission.submitCount);
|
||||
size_t submitSize = directSubmission.getSizeSwitchRingBufferSection();
|
||||
EXPECT_EQ(submitSize, directSubmission.submitSize);
|
||||
EXPECT_EQ(submitGpuVa, directSubmission.submitGpuAddress);
|
||||
EXPECT_EQ(1u, directSubmission.handleResidencyCount);
|
||||
|
||||
EXPECT_EQ(directSubmission.getSizeDispatch(), directSubmission.ringCommandStream.getUsed());
|
||||
EXPECT_TRUE(directSubmission.ringStart);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenSuperBaseCsrWhenCheckingDirectSubmissionAvailableThenReturnFalse) {
|
||||
VariableBackup<UltHwConfig> backup(&ultHwConfig);
|
||||
ultHwConfig.csrSuperBaseCallDirectSubmissionAvailable = true;
|
||||
|
||||
int32_t executionStamp = 0;
|
||||
std::unique_ptr<MockCsr<FamilyType>> mockCsr =
|
||||
std::make_unique<MockCsr<FamilyType>>(executionStamp, *pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
|
||||
bool ret = mockCsr->isDirectSubmissionEnabled();
|
||||
EXPECT_FALSE(ret);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenBaseCsrWhenCheckingDirectSubmissionAvailableThenReturnFalse) {
|
||||
VariableBackup<UltHwConfig> backup(&ultHwConfig);
|
||||
ultHwConfig.csrBaseCallDirectSubmissionAvailable = true;
|
||||
|
||||
int32_t executionStamp = 0;
|
||||
std::unique_ptr<MockCsr<FamilyType>> mockCsr =
|
||||
std::make_unique<MockCsr<FamilyType>>(executionStamp, *pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
|
||||
bool ret = mockCsr->isDirectSubmissionEnabled();
|
||||
EXPECT_FALSE(ret);
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, givenDirectSubmissionAvailableWhenProgrammingEndingCommandThenUseBatchBufferStart) {
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
int32_t executionStamp = 0;
|
||||
std::unique_ptr<MockCsr<FamilyType>> mockCsr =
|
||||
std::make_unique<MockCsr<FamilyType>>(executionStamp, *pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
mockCsr->directSubmissionAvailable = true;
|
||||
bool ret = mockCsr->isDirectSubmissionEnabled();
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
void *location = nullptr;
|
||||
uint8_t buffer[128];
|
||||
mockCsr->commandStream.replaceBuffer(&buffer[0], 128u);
|
||||
mockCsr->programEndingCmd(mockCsr->commandStream, &location, ret);
|
||||
EXPECT_EQ(sizeof(MI_BATCH_BUFFER_START), mockCsr->commandStream.getUsed());
|
||||
|
||||
DispatchFlags dispatchFlags = DispatchFlagsHelper::createDefaultDispatchFlags();
|
||||
dispatchFlags.epilogueRequired = true;
|
||||
size_t expectedSize = sizeof(MI_BATCH_BUFFER_START) +
|
||||
mockCsr->getCmdSizeForEpilogueCommands(dispatchFlags);
|
||||
expectedSize = alignUp(expectedSize, MemoryConstants::cacheLineSize);
|
||||
EXPECT_EQ(expectedSize, mockCsr->getCmdSizeForEpilogue(dispatchFlags));
|
||||
}
|
||||
|
||||
HWTEST_F(DirectSubmissionTest, whenInitDirectSubmissionFailThenEngineIsNotCreated) {
|
||||
VariableBackup<UltHwConfig> backup(&ultHwConfig);
|
||||
ultHwConfig.csrFailInitDirectSubmission = true;
|
||||
bool ret = pDevice->createEngine(0u, aub_stream::ENGINE_RCS);
|
||||
EXPECT_FALSE(ret);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_DIRECT_SUBMISSION_DISPATCHERS_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/blitter_dispatcher_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dispatcher_fixture.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dispatcher_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/render_dispatcher_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_DIRECT_SUBMISSION_DISPATCHERS_TESTS ${NEO_CORE_DIRECT_SUBMISSION_DISPATCHERS_TESTS})
|
||||
add_subdirectories()
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/direct_submission/dispatchers/blitter_dispatcher.h"
|
||||
#include "direct_submission/dispatchers/dispatcher_fixture.h"
|
||||
#include "test.h"
|
||||
|
||||
using BlitterDispatcheTest = Test<DispatcherFixture>;
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
HWTEST_F(BlitterDispatcheTest, givenBlitterWhenAskingForPreemptionCmdSizeThenReturnZero) {
|
||||
BlitterDispatcher<FamilyType> blitterDispatcher;
|
||||
EXPECT_EQ(0u, blitterDispatcher.getSizePreemption());
|
||||
}
|
||||
|
||||
HWTEST_F(BlitterDispatcheTest, givenBlitterWhenDispatchingPreemptionCmdThenDispatchNothing) {
|
||||
BlitterDispatcher<FamilyType> blitterDispatcher;
|
||||
blitterDispatcher.dispatchPreemption(cmdBuffer);
|
||||
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
|
||||
HWTEST_F(BlitterDispatcheTest, givenBlitterWhenAskingForMonitorFenceCmdSizeThenReturnZero) {
|
||||
BlitterDispatcher<FamilyType> blitterDispatcher;
|
||||
EXPECT_EQ(0u, blitterDispatcher.getSizeMonitorFence(pDevice->getHardwareInfo()));
|
||||
}
|
||||
|
||||
HWTEST_F(BlitterDispatcheTest, givenBlitterWhenDispatchingMonitorFenceCmdThenDispatchNothing) {
|
||||
BlitterDispatcher<FamilyType> blitterDispatcher;
|
||||
blitterDispatcher.dispatchMonitorFence(cmdBuffer, MemoryConstants::pageSize64k, 1ull, pDevice->getHardwareInfo());
|
||||
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
HWTEST_F(BlitterDispatcheTest, givenBlitterWhenAskingForCacheFlushCmdSizeThenReturnZero) {
|
||||
BlitterDispatcher<FamilyType> blitterDispatcher;
|
||||
EXPECT_EQ(0u, blitterDispatcher.getSizeCacheFlush(pDevice->getHardwareInfo()));
|
||||
}
|
||||
|
||||
HWTEST_F(BlitterDispatcheTest, givenBlitterWhenDispatchingCacheFlushCmdThenDispatchNothing) {
|
||||
BlitterDispatcher<FamilyType> blitterDispatcher;
|
||||
blitterDispatcher.dispatchCacheFlush(cmdBuffer, pDevice->getHardwareInfo());
|
||||
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "direct_submission/dispatchers/dispatcher_fixture.h"
|
||||
|
||||
#include "shared/source/helpers/aligned_memory.h"
|
||||
#include "shared/source/memory_manager/memory_constants.h"
|
||||
|
||||
void DispatcherFixture::SetUp() {
|
||||
DeviceFixture::SetUp();
|
||||
|
||||
bufferAllocation = alignedMalloc(MemoryConstants::pageSize, MemoryConstants::pageSize);
|
||||
cmdBuffer.replaceBuffer(bufferAllocation, MemoryConstants::pageSize);
|
||||
}
|
||||
|
||||
void DispatcherFixture::TearDown() {
|
||||
alignedFree(bufferAllocation);
|
||||
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/linear_stream.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
|
||||
class DispatcherFixture : public DeviceFixture {
|
||||
public:
|
||||
void SetUp();
|
||||
void TearDown();
|
||||
|
||||
NEO::LinearStream cmdBuffer;
|
||||
void *bufferAllocation;
|
||||
};
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/direct_submission/dispatchers/render_dispatcher.h"
|
||||
#include "direct_submission/dispatchers/dispatcher_fixture.h"
|
||||
#include "fixtures/preemption_fixture.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "test.h"
|
||||
|
||||
using RenderDispatcheTest = Test<DispatcherFixture>;
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
HWTEST_F(RenderDispatcheTest, givenRenderWhenAskingForPreemptionCmdSizeThenReturnSetMmioCmdSize) {
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
|
||||
size_t expectedCmdSize = 0u;
|
||||
if (GetPreemptionTestHwDetails<FamilyType>().supportsPreemptionProgramming()) {
|
||||
expectedCmdSize = sizeof(MI_LOAD_REGISTER_IMM);
|
||||
}
|
||||
RenderDispatcher<FamilyType> renderDispatcher;
|
||||
EXPECT_EQ(expectedCmdSize, renderDispatcher.getSizePreemption());
|
||||
}
|
||||
|
||||
HWTEST_F(RenderDispatcheTest, givenRenderWhenAddingPreemptionCmdThenExpectProperMmioAddress) {
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
|
||||
auto preemptionDetails = GetPreemptionTestHwDetails<FamilyType>();
|
||||
|
||||
RenderDispatcher<FamilyType> renderDispatcher;
|
||||
renderDispatcher.dispatchPreemption(cmdBuffer);
|
||||
|
||||
HardwareParse hwParse;
|
||||
hwParse.parseCommands<FamilyType>(cmdBuffer);
|
||||
MI_LOAD_REGISTER_IMM *immCmd = hwParse.getCommand<MI_LOAD_REGISTER_IMM>();
|
||||
if (preemptionDetails.supportsPreemptionProgramming()) {
|
||||
ASSERT_NE(nullptr, immCmd);
|
||||
uint32_t expectedMmio = preemptionDetails.regAddress;
|
||||
uint32_t expectedValue = preemptionDetails.modeToRegValueMap[PreemptionMode::MidBatch];
|
||||
|
||||
EXPECT_EQ(expectedMmio, immCmd->getRegisterOffset());
|
||||
EXPECT_EQ(expectedValue, immCmd->getDataDword());
|
||||
|
||||
} else {
|
||||
EXPECT_EQ(nullptr, immCmd);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F(RenderDispatcheTest, givenRenderWhenAskingForMonitorFenceCmdSizeThenReturnRequiredPipeControlCmdSize) {
|
||||
size_t expectedSize = MemorySynchronizationCommands<FamilyType>::getSizeForPipeControlWithPostSyncOperation(hardwareInfo);
|
||||
|
||||
RenderDispatcher<FamilyType> renderDispatcher;
|
||||
EXPECT_EQ(expectedSize, renderDispatcher.getSizeMonitorFence(hardwareInfo));
|
||||
}
|
||||
|
||||
HWTEST_F(RenderDispatcheTest, givenRenderWhenAddingMonitorFenceCmdThenExpectPipeControlWithProperAddressAndValue) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
using POST_SYNC_OPERATION = typename FamilyType::PIPE_CONTROL::POST_SYNC_OPERATION;
|
||||
|
||||
uint64_t gpuVa = 0xFF00FF0000ull;
|
||||
uint64_t value = 0x102030;
|
||||
uint32_t gpuVaLow = static_cast<uint32_t>(gpuVa & 0x0000FFFFFFFFull);
|
||||
uint32_t gpuVaHigh = static_cast<uint32_t>(gpuVa >> 32);
|
||||
|
||||
RenderDispatcher<FamilyType> renderDispatcher;
|
||||
renderDispatcher.dispatchMonitorFence(cmdBuffer, gpuVa, value, hardwareInfo);
|
||||
|
||||
HardwareParse hwParse;
|
||||
hwParse.parseCommands<FamilyType>(cmdBuffer);
|
||||
|
||||
bool foundMonitorFence = false;
|
||||
for (auto &it : hwParse.cmdList) {
|
||||
PIPE_CONTROL *pipeControl = genCmdCast<PIPE_CONTROL *>(it);
|
||||
if (pipeControl) {
|
||||
foundMonitorFence =
|
||||
(pipeControl->getPostSyncOperation() == POST_SYNC_OPERATION::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA) &&
|
||||
(pipeControl->getAddress() == gpuVaLow) &&
|
||||
(pipeControl->getAddressHigh() == gpuVaHigh) &&
|
||||
(pipeControl->getImmediateData() == value);
|
||||
if (foundMonitorFence) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(foundMonitorFence);
|
||||
}
|
||||
|
||||
HWTEST_F(RenderDispatcheTest, givenRenderWhenAskingForCacheFlushCmdSizeThenReturnSetRequiredPipeControls) {
|
||||
size_t expectedSize = MemorySynchronizationCommands<FamilyType>::getSizeForFullCacheFlush();
|
||||
|
||||
RenderDispatcher<FamilyType> renderDispatcher;
|
||||
size_t actualSize = renderDispatcher.getSizeCacheFlush(hardwareInfo);
|
||||
EXPECT_EQ(expectedSize, actualSize);
|
||||
}
|
||||
|
||||
HWTEST_F(RenderDispatcheTest, givenRenderWhenAddingCacheFlushCmdThenExpectPipeControlWithProperFields) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
|
||||
RenderDispatcher<FamilyType> renderDispatcher;
|
||||
renderDispatcher.dispatchCacheFlush(cmdBuffer, hardwareInfo);
|
||||
|
||||
HardwareParse hwParse;
|
||||
hwParse.parseCommands<FamilyType>(cmdBuffer);
|
||||
|
||||
bool foundCacheFlush = false;
|
||||
for (auto &it : hwParse.cmdList) {
|
||||
PIPE_CONTROL *pipeControl = genCmdCast<PIPE_CONTROL *>(it);
|
||||
if (pipeControl) {
|
||||
foundCacheFlush =
|
||||
pipeControl->getRenderTargetCacheFlushEnable() &&
|
||||
pipeControl->getInstructionCacheInvalidateEnable() &&
|
||||
pipeControl->getTextureCacheInvalidationEnable() &&
|
||||
pipeControl->getPipeControlFlushEnable() &&
|
||||
pipeControl->getConstantCacheInvalidationEnable() &&
|
||||
pipeControl->getStateCacheInvalidationEnable();
|
||||
if (foundCacheFlush) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(foundCacheFlush);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_DIRECT_SUBMISSION_LINUX_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drm_direct_submission_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_DIRECT_SUBMISSION_LINUX_TESTS ${NEO_CORE_DIRECT_SUBMISSION_LINUX_TESTS})
|
||||
|
||||
add_subdirectories()
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/direct_submission/dispatchers/render_dispatcher.h"
|
||||
#include "shared/source/direct_submission/linux/drm_direct_submission.h"
|
||||
#include "shared/source/os_interface/linux/os_context_linux.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/os_interface/linux/drm_mock.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct DrmDirectSubmissionFixture : public DeviceFixture {
|
||||
void SetUp() {
|
||||
DeviceFixture::SetUp();
|
||||
|
||||
osContext = std::make_unique<OsContextLinux>(drmMock, 0u, 0u, aub_stream::ENGINE_RCS, PreemptionMode::ThreadGroup, false);
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
|
||||
std::unique_ptr<OsContextLinux> osContext;
|
||||
DrmMock drmMock;
|
||||
};
|
||||
|
||||
template <typename GfxFamily>
|
||||
struct MockDrmDirectSubmission : public DrmDirectSubmission<GfxFamily> {
|
||||
MockDrmDirectSubmission(Device &device,
|
||||
std::unique_ptr<Dispatcher> cmdDispatcher,
|
||||
OsContext &osContext)
|
||||
: DrmDirectSubmission<GfxFamily>(device, std::move(cmdDispatcher), osContext) {
|
||||
}
|
||||
using BaseClass = DrmDirectSubmission<GfxFamily>;
|
||||
using BaseClass::allocateOsResources;
|
||||
using BaseClass::getTagAddressValue;
|
||||
using BaseClass::handleResidency;
|
||||
using BaseClass::submit;
|
||||
using BaseClass::switchRingBuffers;
|
||||
using BaseClass::updateTagValue;
|
||||
};
|
||||
|
||||
using DrmDirectSubmissionTest = Test<DrmDirectSubmissionFixture>;
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
HWTEST_F(DrmDirectSubmissionTest, givenDrmDirectSubmissionWhenCallingLinuxImplementationThenExpectAllFailAsNotImplemented) {
|
||||
MockDrmDirectSubmission<FamilyType> drmDirectSubmission(*pDevice,
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
DirectSubmissionAllocations allocations;
|
||||
EXPECT_FALSE(drmDirectSubmission.allocateOsResources(allocations));
|
||||
|
||||
uint64_t gpuAddress = 0x1000;
|
||||
size_t size = 0x1000;
|
||||
EXPECT_FALSE(drmDirectSubmission.submit(gpuAddress, size));
|
||||
|
||||
EXPECT_FALSE(drmDirectSubmission.handleResidency());
|
||||
|
||||
EXPECT_EQ(0ull, drmDirectSubmission.switchRingBuffers());
|
||||
|
||||
EXPECT_EQ(0ull, drmDirectSubmission.updateTagValue());
|
||||
|
||||
TagData tagData = {1ull, 1ull};
|
||||
drmDirectSubmission.getTagAddressValue(tagData);
|
||||
EXPECT_EQ(0ull, tagData.tagAddress);
|
||||
EXPECT_EQ(0ull, tagData.tagValue);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_DIRECT_SUBMISSION_WINDOWS_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm_direct_submission_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_DIRECT_SUBMISSION_WINDOWS_TESTS ${NEO_CORE_DIRECT_SUBMISSION_WINDOWS_TESTS})
|
||||
|
||||
add_subdirectories()
|
||||
@@ -1,380 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/direct_submission/dispatchers/render_dispatcher.h"
|
||||
#include "shared/source/direct_submission/windows/wddm_direct_submission.h"
|
||||
#include "shared/source/os_interface/windows/os_context_win.h"
|
||||
#include "shared/source/os_interface/windows/wddm/wddm.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_device.h"
|
||||
#include "opencl/test/unit_test/os_interface/windows/wddm_fixture.h"
|
||||
|
||||
struct WddmDirectSubmissionFixture : public WddmFixture {
|
||||
void SetUp() override {
|
||||
WddmFixture::SetUp();
|
||||
|
||||
wddm->wddmInterface.reset(new WddmMockInterface20(*wddm));
|
||||
wddmMockInterface = static_cast<WddmMockInterface20 *>(wddm->wddmInterface.get());
|
||||
|
||||
osContext = std::make_unique<OsContextWin>(*wddm, 0u, 0u, aub_stream::ENGINE_RCS, PreemptionMode::ThreadGroup, false);
|
||||
device.reset(MockDevice::create<MockDevice>(executionEnvironment, 0u));
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
}
|
||||
|
||||
WddmMockInterface20 *wddmMockInterface;
|
||||
std::unique_ptr<MockDevice> device;
|
||||
std::unique_ptr<OsContextWin> osContext;
|
||||
};
|
||||
|
||||
template <typename GfxFamily>
|
||||
struct MockWddmDirectSubmission : public WddmDirectSubmission<GfxFamily> {
|
||||
MockWddmDirectSubmission(Device &device,
|
||||
std::unique_ptr<Dispatcher> cmdDispatcher,
|
||||
OsContext &osContext)
|
||||
: WddmDirectSubmission<GfxFamily>(device, std::move(cmdDispatcher), osContext) {
|
||||
}
|
||||
using BaseClass = WddmDirectSubmission<GfxFamily>;
|
||||
using BaseClass::allocateOsResources;
|
||||
using BaseClass::commandBufferHeader;
|
||||
using BaseClass::completionRingBuffers;
|
||||
using BaseClass::currentRingBuffer;
|
||||
using BaseClass::getSizeSwitchRingBufferSection;
|
||||
using BaseClass::getTagAddressValue;
|
||||
using BaseClass::handleCompletionRingBuffer;
|
||||
using BaseClass::handleResidency;
|
||||
using BaseClass::osContextWin;
|
||||
using BaseClass::ringBuffer;
|
||||
using BaseClass::ringBuffer2;
|
||||
using BaseClass::ringCommandStream;
|
||||
using BaseClass::ringFence;
|
||||
using BaseClass::ringStart;
|
||||
using BaseClass::semaphores;
|
||||
using BaseClass::submit;
|
||||
using BaseClass::switchRingBuffers;
|
||||
using BaseClass::updateTagValue;
|
||||
using BaseClass::wddm;
|
||||
using typename BaseClass::RingBufferUse;
|
||||
};
|
||||
|
||||
using WddmDirectSubmissionTest = WddmDirectSubmissionFixture;
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenDirectIsInitializedAndStartedThenExpectProperCommandsDispatched) {
|
||||
std::unique_ptr<MockWddmDirectSubmission<FamilyType>> wddmDirectSubmission =
|
||||
std::make_unique<MockWddmDirectSubmission<FamilyType>>(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
EXPECT_EQ(1u, wddmDirectSubmission->commandBufferHeader->NeedsMidBatchPreEmptionSupport);
|
||||
|
||||
bool ret = wddmDirectSubmission->initialize(true);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_TRUE(wddmDirectSubmission->ringStart);
|
||||
EXPECT_NE(nullptr, wddmDirectSubmission->ringBuffer);
|
||||
EXPECT_NE(nullptr, wddmDirectSubmission->ringBuffer2);
|
||||
EXPECT_NE(nullptr, wddmDirectSubmission->semaphores);
|
||||
|
||||
EXPECT_EQ(1u, wddm->makeResidentResult.called);
|
||||
EXPECT_EQ(3u, wddm->makeResidentResult.handleCount);
|
||||
|
||||
EXPECT_EQ(1u, wddmMockInterface->createMonitoredFenceCalled);
|
||||
|
||||
EXPECT_EQ(1u, wddm->submitResult.called);
|
||||
|
||||
EXPECT_NE(0u, wddmDirectSubmission->ringCommandStream.getUsed());
|
||||
|
||||
*wddmDirectSubmission->ringFence.cpuAddress = 1ull;
|
||||
wddmDirectSubmission->completionRingBuffers[wddmDirectSubmission->currentRingBuffer] = 2ull;
|
||||
|
||||
wddmDirectSubmission.reset(nullptr);
|
||||
EXPECT_EQ(1u, wddm->waitFromCpuResult.called);
|
||||
EXPECT_EQ(1u, wddmMockInterface->destroyMonitorFenceCalled);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenDirectIsInitializedAndNotStartedThenExpectNoCommandsDispatched) {
|
||||
device->setPreemptionMode(PreemptionMode::Disabled);
|
||||
std::unique_ptr<MockWddmDirectSubmission<FamilyType>> wddmDirectSubmission =
|
||||
std::make_unique<MockWddmDirectSubmission<FamilyType>>(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
EXPECT_EQ(0u, wddmDirectSubmission->commandBufferHeader->NeedsMidBatchPreEmptionSupport);
|
||||
|
||||
bool ret = wddmDirectSubmission->initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_FALSE(wddmDirectSubmission->ringStart);
|
||||
EXPECT_NE(nullptr, wddmDirectSubmission->ringBuffer);
|
||||
EXPECT_NE(nullptr, wddmDirectSubmission->ringBuffer2);
|
||||
EXPECT_NE(nullptr, wddmDirectSubmission->semaphores);
|
||||
|
||||
EXPECT_EQ(1u, wddm->makeResidentResult.called);
|
||||
EXPECT_EQ(3u, wddm->makeResidentResult.handleCount);
|
||||
|
||||
EXPECT_EQ(1u, wddmMockInterface->createMonitoredFenceCalled);
|
||||
|
||||
EXPECT_EQ(0u, wddm->submitResult.called);
|
||||
|
||||
EXPECT_EQ(0u, wddmDirectSubmission->ringCommandStream.getUsed());
|
||||
|
||||
wddmDirectSubmission.reset(nullptr);
|
||||
EXPECT_EQ(0u, wddm->waitFromCpuResult.called);
|
||||
EXPECT_EQ(1u, wddmMockInterface->destroyMonitorFenceCalled);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenSubmitingCmdBufferThenExpectPassWddmContextAndProperHeader) {
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
bool ret = wddmDirectSubmission.initialize(false);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
uint64_t gpuAddress = 0xFF00FF000;
|
||||
size_t size = 0xF0;
|
||||
ret = wddmDirectSubmission.submit(gpuAddress, size);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_EQ(1u, wddm->submitResult.called);
|
||||
EXPECT_EQ(gpuAddress, wddm->submitResult.commandBufferSubmitted);
|
||||
EXPECT_EQ(size, wddm->submitResult.size);
|
||||
EXPECT_EQ(wddmDirectSubmission.commandBufferHeader.get(), wddm->submitResult.commandHeaderSubmitted);
|
||||
EXPECT_EQ(&wddmDirectSubmission.ringFence, wddm->submitResult.submitArgs.monitorFence);
|
||||
EXPECT_EQ(osContext->getWddmContextHandle(), wddm->submitResult.submitArgs.contextHandle);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenAllocateOsResourcesThenExpectRingMonitorFenceCreatedAndAllocationsResident) {
|
||||
MemoryManager *memoryManager = device->getExecutionEnvironment()->memoryManager.get();
|
||||
const auto allocationSize = MemoryConstants::pageSize;
|
||||
const AllocationProperties commandStreamAllocationProperties{device->getRootDeviceIndex(),
|
||||
true, allocationSize,
|
||||
GraphicsAllocation::AllocationType::RING_BUFFER,
|
||||
false};
|
||||
GraphicsAllocation *ringBuffer = memoryManager->allocateGraphicsMemoryWithProperties(commandStreamAllocationProperties);
|
||||
ASSERT_NE(nullptr, ringBuffer);
|
||||
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
DirectSubmissionAllocations allocations;
|
||||
allocations.push_back(ringBuffer);
|
||||
|
||||
bool ret = wddmDirectSubmission.allocateOsResources(allocations);
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
EXPECT_EQ(1u, wddmMockInterface->createMonitoredFenceCalled);
|
||||
EXPECT_EQ(1u, wddm->makeResidentResult.called);
|
||||
EXPECT_EQ(1u, wddm->makeResidentResult.handleCount);
|
||||
|
||||
memoryManager->freeGraphicsMemory(ringBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenAllocateOsResourcesFenceCreationFailsThenExpectRingMonitorFenceNotCreatedAndAllocationsNotResident) {
|
||||
MemoryManager *memoryManager = device->getExecutionEnvironment()->memoryManager.get();
|
||||
const auto allocationSize = MemoryConstants::pageSize;
|
||||
const AllocationProperties commandStreamAllocationProperties{device->getRootDeviceIndex(),
|
||||
true, allocationSize,
|
||||
GraphicsAllocation::AllocationType::RING_BUFFER,
|
||||
false};
|
||||
GraphicsAllocation *ringBuffer = memoryManager->allocateGraphicsMemoryWithProperties(commandStreamAllocationProperties);
|
||||
ASSERT_NE(nullptr, ringBuffer);
|
||||
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
DirectSubmissionAllocations allocations;
|
||||
allocations.push_back(ringBuffer);
|
||||
|
||||
wddmMockInterface->createMonitoredFenceCalledFail = true;
|
||||
|
||||
bool ret = wddmDirectSubmission.allocateOsResources(allocations);
|
||||
EXPECT_FALSE(ret);
|
||||
|
||||
EXPECT_EQ(1u, wddmMockInterface->createMonitoredFenceCalled);
|
||||
EXPECT_EQ(0u, wddm->makeResidentResult.called);
|
||||
EXPECT_EQ(0u, wddm->makeResidentResult.handleCount);
|
||||
|
||||
memoryManager->freeGraphicsMemory(ringBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenAllocateOsResourcesResidencyFailsThenExpectRingMonitorFenceCreatedAndAllocationsNotResident) {
|
||||
MemoryManager *memoryManager = device->getExecutionEnvironment()->memoryManager.get();
|
||||
const auto allocationSize = MemoryConstants::pageSize;
|
||||
const AllocationProperties commandStreamAllocationProperties{device->getRootDeviceIndex(),
|
||||
true, allocationSize,
|
||||
GraphicsAllocation::AllocationType::RING_BUFFER,
|
||||
false};
|
||||
GraphicsAllocation *ringBuffer = memoryManager->allocateGraphicsMemoryWithProperties(commandStreamAllocationProperties);
|
||||
ASSERT_NE(nullptr, ringBuffer);
|
||||
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
DirectSubmissionAllocations allocations;
|
||||
allocations.push_back(ringBuffer);
|
||||
|
||||
wddm->callBaseMakeResident = false;
|
||||
wddm->makeResidentStatus = false;
|
||||
|
||||
bool ret = wddmDirectSubmission.allocateOsResources(allocations);
|
||||
EXPECT_FALSE(ret);
|
||||
|
||||
EXPECT_EQ(1u, wddmMockInterface->createMonitoredFenceCalled);
|
||||
//expect 2 makeResident calls, due to fail on 1st and then retry (which also fails)
|
||||
EXPECT_EQ(2u, wddm->makeResidentResult.called);
|
||||
EXPECT_EQ(1u, wddm->makeResidentResult.handleCount);
|
||||
|
||||
memoryManager->freeGraphicsMemory(ringBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenGettingTagDataThenExpectContextMonitorFence) {
|
||||
uint64_t address = 0xFF00FF0000ull;
|
||||
uint64_t value = 0x12345678ull;
|
||||
MonitoredFence &contextFence = osContext->getResidencyController().getMonitoredFence();
|
||||
contextFence.gpuAddress = address;
|
||||
contextFence.currentFenceValue = value;
|
||||
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
TagData tagData;
|
||||
wddmDirectSubmission.getTagAddressValue(tagData);
|
||||
|
||||
EXPECT_EQ(address, tagData.tagAddress);
|
||||
EXPECT_EQ(value, tagData.tagValue);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenHandleResidencyThenExpectWddmWaitOnPaginfFenceFromCpuCalled) {
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
wddmDirectSubmission.handleResidency();
|
||||
|
||||
EXPECT_EQ(1u, wddm->waitOnPagingFenceFromCpuResult.called);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenHandlingRingBufferCompletionThenExpectWaitFromCpuWithCorrectFenceValue) {
|
||||
uint64_t address = 0xFF00FF0000ull;
|
||||
uint64_t value = 0x12345678ull;
|
||||
MonitoredFence &contextFence = osContext->getResidencyController().getMonitoredFence();
|
||||
contextFence.gpuAddress = address;
|
||||
contextFence.currentFenceValue = value;
|
||||
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
uint64_t completionValue = 0x12345679ull;
|
||||
wddmDirectSubmission.handleCompletionRingBuffer(completionValue, contextFence);
|
||||
|
||||
EXPECT_EQ(1u, wddm->waitFromCpuResult.called);
|
||||
EXPECT_EQ(completionValue, wddm->waitFromCpuResult.uint64ParamPassed);
|
||||
EXPECT_EQ(address, wddm->waitFromCpuResult.monitoredFence->gpuAddress);
|
||||
EXPECT_EQ(value, wddm->waitFromCpuResult.monitoredFence->currentFenceValue);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenSwitchingRingBufferStartedThenExpectDispatchSwitchCommandsLinearStreamUpdated) {
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
wddmDirectSubmission.initialize(true);
|
||||
size_t usedSpace = wddmDirectSubmission.ringCommandStream.getUsed();
|
||||
uint64_t expectedGpuVa = wddmDirectSubmission.ringBuffer->getGpuAddress() + usedSpace;
|
||||
|
||||
uint64_t gpuVa = wddmDirectSubmission.switchRingBuffers();
|
||||
EXPECT_EQ(expectedGpuVa, gpuVa);
|
||||
EXPECT_EQ(wddmDirectSubmission.ringBuffer2, wddmDirectSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
|
||||
LinearStream tmpCmdBuffer;
|
||||
tmpCmdBuffer.replaceBuffer(wddmDirectSubmission.ringBuffer->getUnderlyingBuffer(),
|
||||
wddmDirectSubmission.ringCommandStream.getMaxAvailableSpace());
|
||||
tmpCmdBuffer.getSpace(usedSpace + wddmDirectSubmission.getSizeSwitchRingBufferSection());
|
||||
HardwareParse hwParse;
|
||||
hwParse.parseCommands<FamilyType>(tmpCmdBuffer, usedSpace);
|
||||
MI_BATCH_BUFFER_START *bbStart = hwParse.getCommand<MI_BATCH_BUFFER_START>();
|
||||
ASSERT_NE(nullptr, bbStart);
|
||||
EXPECT_EQ(wddmDirectSubmission.ringBuffer2->getGpuAddress(), bbStart->getBatchBufferStartAddressGraphicsaddress472());
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenSwitchingRingBufferNotStartedThenExpectNoSwitchCommandsLinearStreamUpdated) {
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
wddmDirectSubmission.initialize(false);
|
||||
size_t usedSpace = wddmDirectSubmission.ringCommandStream.getUsed();
|
||||
EXPECT_EQ(0u, usedSpace);
|
||||
|
||||
uint64_t expectedGpuVa = wddmDirectSubmission.ringBuffer->getGpuAddress();
|
||||
|
||||
uint64_t gpuVa = wddmDirectSubmission.switchRingBuffers();
|
||||
EXPECT_EQ(expectedGpuVa, gpuVa);
|
||||
EXPECT_EQ(wddmDirectSubmission.ringBuffer2, wddmDirectSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
|
||||
LinearStream tmpCmdBuffer;
|
||||
tmpCmdBuffer.replaceBuffer(wddmDirectSubmission.ringBuffer->getUnderlyingBuffer(),
|
||||
wddmDirectSubmission.ringCommandStream.getMaxAvailableSpace());
|
||||
HardwareParse hwParse;
|
||||
hwParse.parseCommands<FamilyType>(tmpCmdBuffer, 0u);
|
||||
MI_BATCH_BUFFER_START *bbStart = hwParse.getCommand<MI_BATCH_BUFFER_START>();
|
||||
EXPECT_EQ(nullptr, bbStart);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenSwitchingRingBufferStartedAndWaitFenceUpdateThenExpectWaitCalled) {
|
||||
using RingBufferUse = typename MockWddmDirectSubmission<FamilyType>::RingBufferUse;
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
wddmDirectSubmission.initialize(true);
|
||||
uint64_t expectedWaitFence = 0x10ull;
|
||||
wddmDirectSubmission.completionRingBuffers[RingBufferUse::SecondBuffer] = expectedWaitFence;
|
||||
size_t usedSpace = wddmDirectSubmission.ringCommandStream.getUsed();
|
||||
uint64_t expectedGpuVa = wddmDirectSubmission.ringBuffer->getGpuAddress() + usedSpace;
|
||||
|
||||
uint64_t gpuVa = wddmDirectSubmission.switchRingBuffers();
|
||||
EXPECT_EQ(expectedGpuVa, gpuVa);
|
||||
EXPECT_EQ(wddmDirectSubmission.ringBuffer2, wddmDirectSubmission.ringCommandStream.getGraphicsAllocation());
|
||||
|
||||
LinearStream tmpCmdBuffer;
|
||||
tmpCmdBuffer.replaceBuffer(wddmDirectSubmission.ringBuffer->getUnderlyingBuffer(),
|
||||
wddmDirectSubmission.ringCommandStream.getMaxAvailableSpace());
|
||||
tmpCmdBuffer.getSpace(usedSpace + wddmDirectSubmission.getSizeSwitchRingBufferSection());
|
||||
HardwareParse hwParse;
|
||||
hwParse.parseCommands<FamilyType>(tmpCmdBuffer, usedSpace);
|
||||
MI_BATCH_BUFFER_START *bbStart = hwParse.getCommand<MI_BATCH_BUFFER_START>();
|
||||
ASSERT_NE(nullptr, bbStart);
|
||||
EXPECT_EQ(wddmDirectSubmission.ringBuffer2->getGpuAddress(), bbStart->getBatchBufferStartAddressGraphicsaddress472());
|
||||
|
||||
EXPECT_EQ(1u, wddm->waitFromCpuResult.called);
|
||||
EXPECT_EQ(expectedWaitFence, wddm->waitFromCpuResult.uint64ParamPassed);
|
||||
}
|
||||
|
||||
HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenUpdatingTagValueThenExpectCompletionRingBufferUpdated) {
|
||||
uint64_t address = 0xFF00FF0000ull;
|
||||
uint64_t value = 0x12345678ull;
|
||||
MonitoredFence &contextFence = osContext->getResidencyController().getMonitoredFence();
|
||||
contextFence.gpuAddress = address;
|
||||
contextFence.currentFenceValue = value;
|
||||
|
||||
MockWddmDirectSubmission<FamilyType> wddmDirectSubmission(*device.get(),
|
||||
std::make_unique<RenderDispatcher<FamilyType>>(),
|
||||
*osContext.get());
|
||||
|
||||
uint64_t actualTagValue = wddmDirectSubmission.updateTagValue();
|
||||
EXPECT_EQ(value, actualTagValue);
|
||||
EXPECT_EQ(value + 1, contextFence.currentFenceValue);
|
||||
EXPECT_EQ(value, wddmDirectSubmission.completionRingBuffers[wddmDirectSubmission.currentRingBuffer]);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_ENCODERS_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_atomic.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_command_buffer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_dispatch_kernel.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_math.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_media_interface_descriptor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_semaphore.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_set_mmio.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_encode_states.cpp
|
||||
)
|
||||
add_subdirectories()
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_ENCODERS_TESTS ${NEO_CORE_ENCODERS_TESTS})
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
#include "fixtures/command_container_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using CommandEncodeAtomic = Test<CommandEncodeStatesFixture>;
|
||||
|
||||
HWTEST_F(CommandEncodeAtomic, programMiAtomic) {
|
||||
using MI_ATOMIC = typename FamilyType::MI_ATOMIC;
|
||||
MI_ATOMIC miAtomic;
|
||||
|
||||
EncodeAtomic<FamilyType>::programMiAtomic(&miAtomic, 0x123400, MI_ATOMIC::ATOMIC_OPCODES::ATOMIC_4B_DECREMENT,
|
||||
MI_ATOMIC::DATA_SIZE::DATA_SIZE_DWORD);
|
||||
|
||||
EXPECT_EQ(MI_ATOMIC::ATOMIC_OPCODES::ATOMIC_4B_DECREMENT, miAtomic.getAtomicOpcode());
|
||||
EXPECT_EQ(MI_ATOMIC::DATA_SIZE::DATA_SIZE_DWORD, miAtomic.getDataSize());
|
||||
EXPECT_EQ(0x123400u, miAtomic.getMemoryAddress());
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_container/cmdcontainer.h"
|
||||
#include "shared/source/command_container/command_encoder.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using EncodeBatchBufferStartOrEndTest = Test<DeviceFixture>;
|
||||
|
||||
HWTEST_F(EncodeBatchBufferStartOrEndTest, givenCommandContainerWhenEncodeBBEndThenCommandIsAdded) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeBatchBufferStartOrEnd<FamilyType>::programBatchBufferEnd(cmdContainer);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_BATCH_BUFFER_END = typename FamilyType::MI_BATCH_BUFFER_END;
|
||||
auto itor = find<MI_BATCH_BUFFER_END *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
}
|
||||
|
||||
HWTEST_F(EncodeBatchBufferStartOrEndTest, givenCommandContainerWhenEncodeBBStartThenCommandIsAdded) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeBatchBufferStartOrEnd<FamilyType>::programBatchBufferStart(cmdContainer.getCommandStream(), 0, true);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
auto itor = find<MI_BATCH_BUFFER_START *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
}
|
||||
|
||||
HWTEST_F(EncodeBatchBufferStartOrEndTest, givenCommandContainerWhenEncodeBBStartWithSecondLevelParameterThenCommandIsProgrammedCorrectly) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeBatchBufferStartOrEnd<FamilyType>::programBatchBufferStart(cmdContainer.getCommandStream(), 0, true);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
auto itor = find<MI_BATCH_BUFFER_START *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
{
|
||||
auto cmd = genCmdCast<MI_BATCH_BUFFER_START *>(*itor);
|
||||
EXPECT_EQ(MI_BATCH_BUFFER_START::SECOND_LEVEL_BATCH_BUFFER_SECOND_LEVEL_BATCH, cmd->getSecondLevelBatchBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F(EncodeBatchBufferStartOrEndTest, givenCommandContainerWhenEncodeBBStartWithFirstLevelParameterThenCommandIsProgrammedCorrectly) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeBatchBufferStartOrEnd<FamilyType>::programBatchBufferStart(cmdContainer.getCommandStream(), 0, false);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
auto itor = find<MI_BATCH_BUFFER_START *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
{
|
||||
auto cmd = genCmdCast<MI_BATCH_BUFFER_START *>(*itor);
|
||||
EXPECT_EQ(MI_BATCH_BUFFER_START::SECOND_LEVEL_BATCH_BUFFER_FIRST_LEVEL_BATCH, cmd->getSecondLevelBatchBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F(EncodeBatchBufferStartOrEndTest, givenGpuAddressWhenEncodeBBStartThenAddressIsProgrammedCorrectly) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
|
||||
uint64_t gpuAddress = 12 * MemoryConstants::pageSize;
|
||||
EncodeBatchBufferStartOrEnd<FamilyType>::programBatchBufferStart(cmdContainer.getCommandStream(), gpuAddress, false);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
|
||||
auto itor = find<MI_BATCH_BUFFER_START *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
{
|
||||
auto cmd = genCmdCast<MI_BATCH_BUFFER_START *>(*itor);
|
||||
EXPECT_EQ(gpuAddress, cmd->getBatchBufferStartAddressGraphicsaddress472());
|
||||
}
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
#include "fixtures/command_container_fixture.h"
|
||||
#include "mocks/mock_dispatch_kernel_encoder_interface.h"
|
||||
#include "opencl/source/helpers/hardware_commands_helper.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using CommandEncodeStatesTest = Test<CommandEncodeStatesFixture>;
|
||||
|
||||
TEST_F(CommandEncodeStatesTest, givenDefaultCommandConatinerGetNumIddsInBlock) {
|
||||
auto numIdds = cmdContainer->getNumIddPerBlock();
|
||||
EXPECT_EQ(64u, numIdds);
|
||||
}
|
||||
|
||||
TEST_F(CommandEncodeStatesTest, givenCommandConatinerCreatedWithMaxNumAggregateIddThenVerifyGetNumIddsInBlockIsCorrect) {
|
||||
auto cmdContainer = new CommandContainer(1);
|
||||
auto numIdds = cmdContainer->getNumIddPerBlock();
|
||||
|
||||
EXPECT_EQ(1u, numIdds);
|
||||
|
||||
delete cmdContainer;
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenenDispatchInterfaceWhenDispatchKernelThenWalkerCommandProgrammed) {
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
using WALKER_TYPE = typename FamilyType::WALKER_TYPE;
|
||||
auto itorPC = find<WALKER_TYPE *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorPC, commands.end());
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenCommandContainerWithUsedAvailableSizeWhenDispatchKernelThenNextCommandBufferIsAdded) {
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
auto cmdBuffersCountBefore = cmdContainer->getCmdBufferAllocations().size();
|
||||
|
||||
cmdContainer->getCommandStream()->getSpace(cmdContainer->getCommandStream()->getAvailableSpace() - sizeof(typename FamilyType::MI_BATCH_BUFFER_END));
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
auto cmdBuffersCountAfter = cmdContainer->getCmdBufferAllocations().size();
|
||||
|
||||
EXPECT_GT(cmdBuffersCountAfter, cmdBuffersCountBefore);
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, givenSlmTotalSizeGraterThanZeroWhenDispatchingKernelThenSharedMemorySizeSetCorrectly) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
using STATE_BASE_ADDRESS = typename FamilyType::STATE_BASE_ADDRESS;
|
||||
using SAMPLER_STATE = typename FamilyType::SAMPLER_STATE;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
uint32_t slmTotalSize = 1;
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSlmTotalSize()).WillRepeatedly(::testing::Return(slmTotalSize));
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
auto interfaceDescriptorData = static_cast<INTERFACE_DESCRIPTOR_DATA *>(cmdContainer->getIddBlock());
|
||||
|
||||
uint32_t expectedValue = static_cast<typename INTERFACE_DESCRIPTOR_DATA::SHARED_LOCAL_MEMORY_SIZE>(HardwareCommandsHelper<FamilyType>::computeSlmValues(slmTotalSize));
|
||||
|
||||
EXPECT_EQ(expectedValue, interfaceDescriptorData->getSharedLocalMemorySize());
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, givenSlmTotalSizeEqualZeroWhenDispatchingKernelThenSharedMemorySizeSetCorrectly) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
using STATE_BASE_ADDRESS = typename FamilyType::STATE_BASE_ADDRESS;
|
||||
using SAMPLER_STATE = typename FamilyType::SAMPLER_STATE;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
uint32_t slmTotalSize = 0;
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSlmTotalSize()).WillRepeatedly(::testing::Return(slmTotalSize));
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
auto interfaceDescriptorData = static_cast<INTERFACE_DESCRIPTOR_DATA *>(cmdContainer->getIddBlock());
|
||||
|
||||
uint32_t expectedValue = INTERFACE_DESCRIPTOR_DATA::SHARED_LOCAL_MEMORY_SIZE_ENCODES_0K;
|
||||
|
||||
EXPECT_EQ(expectedValue, interfaceDescriptorData->getSharedLocalMemorySize());
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, givennumBindingTableOneWhenDispatchingKernelThenBindingTableOffsetIsCorrect) {
|
||||
using BINDING_TABLE_STATE = typename FamilyType::BINDING_TABLE_STATE;
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
uint32_t numBindingTable = 1;
|
||||
BINDING_TABLE_STATE bindingTableState;
|
||||
bindingTableState.sInit();
|
||||
|
||||
auto ssh = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
|
||||
uint32_t sizeUsed = 0x20;
|
||||
ssh->getSpace(sizeUsed);
|
||||
auto expectedOffset = alignUp(sizeUsed, BINDING_TABLE_STATE::SURFACESTATEPOINTER_ALIGN_SIZE);
|
||||
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
EXPECT_CALL(*dispatchInterface.get(), getNumSurfaceStates()).WillRepeatedly(::testing::Return(numBindingTable));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSurfaceStateHeap()).WillRepeatedly(::testing::Return(&bindingTableState));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSizeSurfaceStateHeapData()).WillRepeatedly(::testing::Return(static_cast<uint32_t>(sizeof(BINDING_TABLE_STATE))));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getBindingTableOffset()).WillRepeatedly(::testing::Return(0));
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
auto interfaceDescriptorData = static_cast<INTERFACE_DESCRIPTOR_DATA *>(cmdContainer->getIddBlock());
|
||||
|
||||
EXPECT_EQ(interfaceDescriptorData->getBindingTablePointer(), expectedOffset);
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, giveNumBindingTableZeroWhenDispatchingKernelThenBindingTableOffsetIsZero) {
|
||||
using BINDING_TABLE_STATE = typename FamilyType::BINDING_TABLE_STATE;
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
uint32_t numBindingTable = 0;
|
||||
BINDING_TABLE_STATE bindingTableState;
|
||||
bindingTableState.sInit();
|
||||
|
||||
auto ssh = cmdContainer->getIndirectHeap(HeapType::SURFACE_STATE);
|
||||
uint32_t sizeUsed = 0x20;
|
||||
ssh->getSpace(sizeUsed);
|
||||
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
EXPECT_CALL(*dispatchInterface.get(), getNumSurfaceStates()).WillRepeatedly(::testing::Return(numBindingTable));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSurfaceStateHeap()).WillRepeatedly(::testing::Return(&bindingTableState));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSizeSurfaceStateHeapData()).WillRepeatedly(::testing::Return(static_cast<uint32_t>(sizeof(BINDING_TABLE_STATE))));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getBindingTableOffset()).WillRepeatedly(::testing::Return(0));
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
auto interfaceDescriptorData = static_cast<INTERFACE_DESCRIPTOR_DATA *>(cmdContainer->getIddBlock());
|
||||
|
||||
EXPECT_EQ(interfaceDescriptorData->getBindingTablePointer(), 0u);
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, giveNumSamplersOneWhenDispatchingKernelThensamplerStateWasCopied) {
|
||||
using SAMPLER_STATE = typename FamilyType::SAMPLER_STATE;
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
uint32_t numSamplers = 1;
|
||||
SAMPLER_STATE samplerState;
|
||||
memset(&samplerState, 2, sizeof(SAMPLER_STATE));
|
||||
|
||||
auto dsh = cmdContainer->getIndirectHeap(HeapType::DYNAMIC_STATE);
|
||||
auto usedBefore = dsh->getUsed();
|
||||
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
EXPECT_CALL(*dispatchInterface.get(), getNumSamplers()).WillRepeatedly(::testing::Return(numSamplers));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSamplerTableOffset()).WillRepeatedly(::testing::Return(0));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getBorderColor()).WillRepeatedly(::testing::Return(0));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getDynamicStateHeap()).WillRepeatedly(::testing::Return(&samplerState));
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
auto interfaceDescriptorData = static_cast<INTERFACE_DESCRIPTOR_DATA *>(cmdContainer->getIddBlock());
|
||||
|
||||
auto borderColorOffsetInDsh = usedBefore;
|
||||
samplerState.setIndirectStatePointer(static_cast<uint32_t>(borderColorOffsetInDsh));
|
||||
|
||||
auto samplerStateOffset = interfaceDescriptorData->getSamplerStatePointer();
|
||||
|
||||
auto pSmplr = reinterpret_cast<SAMPLER_STATE *>(ptrOffset(dsh->getCpuBase(), samplerStateOffset));
|
||||
EXPECT_EQ(memcmp(pSmplr, &samplerState, sizeof(SAMPLER_STATE)), 0);
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, giveNumSamplersZeroWhenDispatchingKernelThensamplerStateWasNotCopied) {
|
||||
using SAMPLER_STATE = typename FamilyType::SAMPLER_STATE;
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
uint32_t numSamplers = 0;
|
||||
SAMPLER_STATE samplerState;
|
||||
memset(&samplerState, 2, sizeof(SAMPLER_STATE));
|
||||
|
||||
auto dsh = cmdContainer->getIndirectHeap(HeapType::DYNAMIC_STATE);
|
||||
auto usedBefore = dsh->getUsed();
|
||||
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
EXPECT_CALL(*dispatchInterface.get(), getNumSamplers()).WillRepeatedly(::testing::Return(numSamplers));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSamplerTableOffset()).WillRepeatedly(::testing::Return(0));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getBorderColor()).WillRepeatedly(::testing::Return(0));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getDynamicStateHeap()).WillRepeatedly(::testing::Return(&samplerState));
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
auto interfaceDescriptorData = static_cast<INTERFACE_DESCRIPTOR_DATA *>(cmdContainer->getIddBlock());
|
||||
|
||||
auto borderColorOffsetInDsh = usedBefore;
|
||||
samplerState.setIndirectStatePointer(static_cast<uint32_t>(borderColorOffsetInDsh));
|
||||
|
||||
auto samplerStateOffset = interfaceDescriptorData->getSamplerStatePointer();
|
||||
|
||||
auto pSmplr = reinterpret_cast<SAMPLER_STATE *>(ptrOffset(dsh->getCpuBase(), samplerStateOffset));
|
||||
EXPECT_NE(memcmp(pSmplr, &samplerState, sizeof(SAMPLER_STATE)), 0);
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenIndarectOffsetsCountsWhenDispatchingKernelThenCorrestMIStoreOffsetsSet) {
|
||||
using MI_STORE_REGISTER_MEM = typename FamilyType::MI_STORE_REGISTER_MEM;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
uint32_t offsets[] = {0x10, 0x20, 0x30};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
EXPECT_CALL(*dispatchInterface.get(), hasGroupCounts()).WillRepeatedly(::testing::Return(true));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getCountOffsets()).WillRepeatedly(::testing::Return(offsets));
|
||||
EXPECT_CALL(*dispatchInterface.get(), hasGroupSize()).WillRepeatedly(::testing::Return(false));
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, true, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itor = commands.begin();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ASSERT_NE(itor, commands.end());
|
||||
itor = find<MI_STORE_REGISTER_MEM *>(++itor, commands.end());
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenIndarectOffsetsSizeWhenDispatchingKernelThenMiMathEncoded) {
|
||||
using MI_MATH = typename FamilyType::MI_MATH;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
uint32_t offsets[] = {0x10, 0x20, 0x30};
|
||||
uint32_t lws[] = {1, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
EXPECT_CALL(*dispatchInterface.get(), hasGroupCounts()).WillRepeatedly(::testing::Return(false));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSizeOffsets()).WillRepeatedly(::testing::Return(offsets));
|
||||
EXPECT_CALL(*dispatchInterface.get(), hasGroupSize()).WillRepeatedly(::testing::Return(true));
|
||||
EXPECT_CALL(*dispatchInterface.get(), getLocalWorkSize()).WillRepeatedly(::testing::Return(lws));
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, true, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itor = find<MI_MATH *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, givenCleanHeapsAndSlmNotChangedWhenDispatchKernelThenFlushNotAdded) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
cmdContainer->slmSize = 1;
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSlmTotalSize()).WillRepeatedly(::testing::Return(cmdContainer->slmSize));
|
||||
cmdContainer->setDirtyStateForAllHeaps(false);
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(commands.begin(), commands.end());
|
||||
ASSERT_EQ(itorPC, commands.end());
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, givenDirtyHeapsAndSlmNotChangedWhenDispatchKernelThenHeapsAreCleanAndFlushAdded) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
cmdContainer->slmSize = 1;
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSlmTotalSize()).WillRepeatedly(::testing::Return(cmdContainer->slmSize));
|
||||
cmdContainer->setDirtyStateForAllHeaps(true);
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorPC, commands.end());
|
||||
EXPECT_FALSE(cmdContainer->isAnyHeapDirty());
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, givenCleanHeapsAndSlmChangedWhenDispatchKernelThenFlushAdded) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
EXPECT_CALL(*dispatchInterface.get(), getSlmTotalSize()).WillRepeatedly(::testing::Return(cmdContainer->slmSize + 1));
|
||||
cmdContainer->setDirtyStateForAllHeaps(false);
|
||||
|
||||
auto slmSizeBefore = cmdContainer->slmSize;
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorPC, commands.end());
|
||||
EXPECT_EQ(slmSizeBefore + 1, cmdContainer->slmSize);
|
||||
}
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, giveNextIddInBlockZeorWhenDispatchKernelThenMediaInterfaceDescriptorEncoded) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
using MEDIA_INTERFACE_DESCRIPTOR_LOAD = typename FamilyType::MEDIA_INTERFACE_DESCRIPTOR_LOAD;
|
||||
uint32_t dims[] = {2, 1, 1};
|
||||
std::unique_ptr<MockDispatchKernelEncoder> dispatchInterface(new MockDispatchKernelEncoder());
|
||||
|
||||
cmdContainer->getIndirectHeap(HeapType::DYNAMIC_STATE)->align(HardwareCommandsHelper<FamilyType>::alignInterfaceDescriptorData);
|
||||
cmdContainer->setIddBlock(cmdContainer->getHeapSpaceAllowGrow(HeapType::DYNAMIC_STATE, sizeof(INTERFACE_DESCRIPTOR_DATA) * cmdContainer->getNumIddPerBlock()));
|
||||
cmdContainer->nextIddInBlock = 0;
|
||||
|
||||
EncodeDispatchKernel<FamilyType>::encode(*cmdContainer.get(), dims, false, false, dispatchInterface.get(), 0, pDevice, NEO::PreemptionMode::Disabled);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itorPC = find<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorPC, commands.end());
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_container/command_encoder.h"
|
||||
#include "shared/source/helpers/register_offsets.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using EncodeMathMMIOTest = testing::Test;
|
||||
|
||||
HWTEST_F(EncodeMathMMIOTest, encodeAluAddHasCorrectOpcodesOperands) {
|
||||
using MI_MATH_ALU_INST_INLINE = typename FamilyType::MI_MATH_ALU_INST_INLINE;
|
||||
|
||||
MI_MATH_ALU_INST_INLINE aluParam[5];
|
||||
uint32_t regA = ALU_REGISTER_R_0;
|
||||
uint32_t regB = ALU_REGISTER_R_1;
|
||||
|
||||
memset(aluParam, 0, sizeof(MI_MATH_ALU_INST_INLINE) * 5);
|
||||
|
||||
EncodeMathMMIO<FamilyType>::encodeAluAdd(aluParam, regA, regB);
|
||||
|
||||
EXPECT_EQ(aluParam[0].DW0.BitField.ALUOpcode, ALU_OPCODE_LOAD);
|
||||
EXPECT_EQ(aluParam[0].DW0.BitField.Operand1, ALU_REGISTER_R_SRCA);
|
||||
EXPECT_EQ(aluParam[0].DW0.BitField.Operand2, regA);
|
||||
|
||||
EXPECT_EQ(aluParam[1].DW0.BitField.ALUOpcode, ALU_OPCODE_LOAD);
|
||||
EXPECT_EQ(aluParam[1].DW0.BitField.Operand1, ALU_REGISTER_R_SRCB);
|
||||
EXPECT_EQ(aluParam[1].DW0.BitField.Operand2, regB);
|
||||
|
||||
EXPECT_EQ(aluParam[2].DW0.BitField.ALUOpcode, ALU_OPCODE_ADD);
|
||||
EXPECT_EQ(aluParam[2].DW0.BitField.Operand1, 0u);
|
||||
EXPECT_EQ(aluParam[2].DW0.BitField.Operand2, 0u);
|
||||
|
||||
EXPECT_EQ(aluParam[3].DW0.BitField.ALUOpcode, ALU_OPCODE_STORE);
|
||||
EXPECT_EQ(aluParam[3].DW0.BitField.Operand1, ALU_REGISTER_R_0);
|
||||
EXPECT_EQ(aluParam[3].DW0.BitField.Operand2, ALU_REGISTER_R_ACCU);
|
||||
|
||||
EXPECT_EQ(aluParam[4].DW0.Value, 0u);
|
||||
}
|
||||
|
||||
HWTEST_F(EncodeMathMMIOTest, encodeAluSubStoreCarryHasCorrectOpcodesOperands) {
|
||||
using MI_MATH_ALU_INST_INLINE = typename FamilyType::MI_MATH_ALU_INST_INLINE;
|
||||
|
||||
MI_MATH_ALU_INST_INLINE aluParam[5];
|
||||
uint32_t regA = ALU_REGISTER_R_0;
|
||||
uint32_t regB = ALU_REGISTER_R_1;
|
||||
uint32_t finalResultRegister = ALU_REGISTER_R_2;
|
||||
|
||||
memset(aluParam, 0, sizeof(MI_MATH_ALU_INST_INLINE) * 5);
|
||||
|
||||
EncodeMathMMIO<FamilyType>::encodeAluSubStoreCarry(aluParam, regA, regB,
|
||||
finalResultRegister);
|
||||
|
||||
EXPECT_EQ(aluParam[0].DW0.BitField.ALUOpcode, ALU_OPCODE_LOAD);
|
||||
EXPECT_EQ(aluParam[0].DW0.BitField.Operand1, ALU_REGISTER_R_SRCA);
|
||||
EXPECT_EQ(aluParam[0].DW0.BitField.Operand2, regA);
|
||||
|
||||
EXPECT_EQ(aluParam[1].DW0.BitField.ALUOpcode, ALU_OPCODE_LOAD);
|
||||
EXPECT_EQ(aluParam[1].DW0.BitField.Operand1, ALU_REGISTER_R_SRCB);
|
||||
EXPECT_EQ(aluParam[1].DW0.BitField.Operand2, regB);
|
||||
|
||||
EXPECT_EQ(aluParam[2].DW0.BitField.ALUOpcode, ALU_OPCODE_SUB);
|
||||
EXPECT_EQ(aluParam[2].DW0.BitField.Operand1, 0u);
|
||||
EXPECT_EQ(aluParam[2].DW0.BitField.Operand2, 0u);
|
||||
|
||||
EXPECT_EQ(aluParam[3].DW0.BitField.ALUOpcode, ALU_OPCODE_STORE);
|
||||
EXPECT_EQ(aluParam[3].DW0.BitField.Operand1, ALU_REGISTER_R_2);
|
||||
EXPECT_EQ(aluParam[3].DW0.BitField.Operand2, ALU_REGISTER_R_CF);
|
||||
|
||||
EXPECT_EQ(aluParam[4].DW0.Value, 0u);
|
||||
}
|
||||
|
||||
using CommandEncoderMathTest = Test<DeviceFixture>;
|
||||
|
||||
HWTEST_F(CommandEncoderMathTest, appendsAGreaterThanPredicate) {
|
||||
using MI_LOAD_REGISTER_MEM = typename FamilyType::MI_LOAD_REGISTER_MEM;
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
using MI_LOAD_REGISTER_REG = typename FamilyType::MI_LOAD_REGISTER_REG;
|
||||
using MI_MATH = typename FamilyType::MI_MATH;
|
||||
using MI_MATH_ALU_INST_INLINE = typename FamilyType::MI_MATH_ALU_INST_INLINE;
|
||||
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
|
||||
EncodeMathMMIO<FamilyType>::encodeGreaterThanPredicate(cmdContainer, 0xDEADBEEFCAF0u, 17u);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
auto itor = commands.begin();
|
||||
|
||||
itor = find<MI_LOAD_REGISTER_IMM *>(itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
auto cmdIMM = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itor);
|
||||
EXPECT_EQ(cmdIMM->getRegisterOffset(), CS_GPR_R0);
|
||||
EXPECT_EQ(cmdIMM->getDataDword(), 17u);
|
||||
|
||||
itor = find<MI_LOAD_REGISTER_MEM *>(itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
auto cmdMEM = genCmdCast<MI_LOAD_REGISTER_MEM *>(*itor);
|
||||
EXPECT_EQ(cmdMEM->getRegisterAddress(), CS_GPR_R1);
|
||||
EXPECT_EQ(cmdMEM->getMemoryAddress(), 0xDEADBEEFCAF0u);
|
||||
|
||||
itor = find<MI_MATH *>(itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
auto cmdMATH = genCmdCast<MI_MATH *>(*itor);
|
||||
EXPECT_EQ(cmdMATH->DW0.BitField.DwordLength, 3u);
|
||||
|
||||
itor = find<MI_LOAD_REGISTER_REG *>(itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
auto cmdREG = genCmdCast<MI_LOAD_REGISTER_REG *>(*itor);
|
||||
EXPECT_EQ(cmdREG->getSourceRegisterAddress(), CS_GPR_R2);
|
||||
EXPECT_EQ(cmdREG->getDestinationRegisterAddress(), CS_PREDICATE_RESULT);
|
||||
|
||||
auto cmdALU = reinterpret_cast<MI_MATH_ALU_INST_INLINE *>(cmdMATH + 3);
|
||||
EXPECT_EQ(cmdALU->DW0.BitField.ALUOpcode, ALU_OPCODE_SUB);
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncoderMathTest, setGroupSizeIndirect) {
|
||||
using MI_MATH = typename FamilyType::MI_MATH;
|
||||
using MI_MATH_ALU_INST_INLINE = typename FamilyType::MI_MATH_ALU_INST_INLINE;
|
||||
using MI_STORE_REGISTER_MEM = typename FamilyType::MI_STORE_REGISTER_MEM;
|
||||
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
|
||||
uint32_t offsets[3] = {0, sizeof(uint32_t), 2 * sizeof(uint32_t)};
|
||||
uint32_t crossThreadAdress[3] = {};
|
||||
uint32_t lws[3] = {2, 1, 1};
|
||||
|
||||
EncodeIndirectParams<FamilyType>::setGroupSizeIndirect(cmdContainer, offsets, crossThreadAdress, lws);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
auto itor = commands.begin();
|
||||
|
||||
itor = find<MI_MATH *>(itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
itor = find<MI_STORE_REGISTER_MEM *>(itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncoderMathTest, setGroupCountIndirect) {
|
||||
using MI_MATH = typename FamilyType::MI_MATH;
|
||||
using MI_MATH_ALU_INST_INLINE = typename FamilyType::MI_MATH_ALU_INST_INLINE;
|
||||
using MI_STORE_REGISTER_MEM = typename FamilyType::MI_STORE_REGISTER_MEM;
|
||||
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
|
||||
uint32_t offsets[3] = {0, sizeof(uint32_t), 2 * sizeof(uint32_t)};
|
||||
uint32_t crossThreadAdress[3] = {};
|
||||
|
||||
EncodeIndirectParams<FamilyType>::setGroupCountIndirect(cmdContainer, offsets, crossThreadAdress);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
auto itor = commands.begin();
|
||||
|
||||
itor = find<MI_STORE_REGISTER_MEM *>(itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
itor = find<MI_STORE_REGISTER_MEM *>(++itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
itor = find<MI_STORE_REGISTER_MEM *>(++itor, commands.end());
|
||||
ASSERT_NE(itor, commands.end());
|
||||
|
||||
itor = find<MI_STORE_REGISTER_MEM *>(++itor, commands.end());
|
||||
ASSERT_EQ(itor, commands.end());
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
#include "fixtures/command_container_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using CommandEncodeStatesTest = Test<CommandEncodeStatesFixture>;
|
||||
|
||||
HWCMDTEST_F(IGFX_GEN8_CORE, CommandEncodeStatesTest, ecodeMediaInterfaceDescriptor) {
|
||||
using MEDIA_STATE_FLUSH = typename FamilyType::MEDIA_STATE_FLUSH;
|
||||
using MEDIA_INTERFACE_DESCRIPTOR_LOAD = typename FamilyType::MEDIA_INTERFACE_DESCRIPTOR_LOAD;
|
||||
|
||||
EncodeMediaInterfaceDescriptorLoad<FamilyType>::encode(*cmdContainer.get());
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itorCmd = find<MEDIA_STATE_FLUSH *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorCmd, commands.end());
|
||||
|
||||
itorCmd = find<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(++itorCmd, commands.end());
|
||||
ASSERT_NE(itorCmd, commands.end());
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/linear_stream.h"
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
#include "fixtures/command_container_fixture.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using CommandEncodeSemaphore = Test<CommandEncodeStatesFixture>;
|
||||
|
||||
HWTEST_F(CommandEncodeSemaphore, programMiSemaphoreWait) {
|
||||
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
|
||||
MI_SEMAPHORE_WAIT miSemaphore;
|
||||
|
||||
EncodeSempahore<FamilyType>::programMiSemaphoreWait(&miSemaphore,
|
||||
0x123400,
|
||||
4,
|
||||
MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_NOT_EQUAL_SDD);
|
||||
|
||||
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_NOT_EQUAL_SDD, miSemaphore.getCompareOperation());
|
||||
EXPECT_EQ(4u, miSemaphore.getSemaphoreDataDword());
|
||||
EXPECT_EQ(0x123400u, miSemaphore.getSemaphoreGraphicsAddress());
|
||||
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, miSemaphore.getWaitMode());
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeSemaphore, whenAddingMiSemaphoreCommandThenExpectCompareFieldsAreSetCorrectly) {
|
||||
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
|
||||
using COMPARE_OPERATION = typename FamilyType::MI_SEMAPHORE_WAIT::COMPARE_OPERATION;
|
||||
using WAIT_MODE = typename FamilyType::MI_SEMAPHORE_WAIT::WAIT_MODE;
|
||||
|
||||
std::unique_ptr<uint8_t> buffer(new uint8_t[128]);
|
||||
LinearStream stream(buffer.get(), 128);
|
||||
COMPARE_OPERATION compareMode = COMPARE_OPERATION::COMPARE_OPERATION_SAD_GREATER_THAN_OR_EQUAL_SDD;
|
||||
|
||||
EncodeSempahore<FamilyType>::addMiSemaphoreWaitCommand(stream,
|
||||
0xFF00FF000u,
|
||||
5u,
|
||||
compareMode);
|
||||
|
||||
EXPECT_EQ(sizeof(MI_SEMAPHORE_WAIT), stream.getUsed());
|
||||
|
||||
HardwareParse hwParse;
|
||||
hwParse.parseCommands<FamilyType>(stream);
|
||||
MI_SEMAPHORE_WAIT *miSemaphore = hwParse.getCommand<MI_SEMAPHORE_WAIT>();
|
||||
ASSERT_NE(nullptr, miSemaphore);
|
||||
|
||||
EXPECT_EQ(compareMode, miSemaphore->getCompareOperation());
|
||||
EXPECT_EQ(5u, miSemaphore->getSemaphoreDataDword());
|
||||
EXPECT_EQ(0xFF00FF000u, miSemaphore->getSemaphoreGraphicsAddress());
|
||||
EXPECT_EQ(WAIT_MODE::WAIT_MODE_POLLING_MODE, miSemaphore->getWaitMode());
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeSemaphore, whenGettingMiSemaphoreCommandSizeThenExpectSingleMiSemaphoreCommandSize) {
|
||||
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
|
||||
size_t expectedSize = sizeof(MI_SEMAPHORE_WAIT);
|
||||
size_t actualSize = EncodeSempahore<FamilyType>::getSizeMiSemaphoreWait();
|
||||
EXPECT_EQ(expectedSize, actualSize);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_container/command_encoder.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class CommandSetMMIOFixture : public DeviceFixture {
|
||||
public:
|
||||
void SetUp() {
|
||||
DeviceFixture::SetUp();
|
||||
cmdContainer = std::make_unique<CommandContainer>();
|
||||
cmdContainer->initialize(pDevice);
|
||||
}
|
||||
void TearDown() {
|
||||
cmdContainer.reset();
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
std::unique_ptr<CommandContainer> cmdContainer;
|
||||
};
|
||||
|
||||
using CommandSetMMIOTest = Test<CommandSetMMIOFixture>;
|
||||
|
||||
HWTEST_F(CommandSetMMIOTest, appendsAMI_LOAD_REGISTER_IMM) {
|
||||
EncodeSetMMIO<FamilyType>::encodeIMM(*cmdContainer.get(), 0xf00, 0xbaa);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorLRI, commands.end());
|
||||
{
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
EXPECT_EQ(cmd->getRegisterOffset(), 0xf00u);
|
||||
EXPECT_EQ(cmd->getDataDword(), 0xbaau);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F(CommandSetMMIOTest, appendsAMI_LOAD_REGISTER_MEM) {
|
||||
EncodeSetMMIO<FamilyType>::encodeMEM(*cmdContainer.get(), 0xf00, 0xDEADBEEFCAF0);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
using MI_LOAD_REGISTER_MEM = typename FamilyType::MI_LOAD_REGISTER_MEM;
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_MEM *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorLRI, commands.end());
|
||||
{
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_MEM *>(*itorLRI);
|
||||
EXPECT_EQ(cmd->getRegisterAddress(), 0xf00u);
|
||||
EXPECT_EQ(cmd->getMemoryAddress(), 0xDEADBEEFCAF0u);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F(CommandSetMMIOTest, appendsAMI_LOAD_REGISTER_REG) {
|
||||
EncodeSetMMIO<FamilyType>::encodeREG(*cmdContainer.get(), 0xf10, 0xaf0);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
using MI_LOAD_REGISTER_REG = typename FamilyType::MI_LOAD_REGISTER_REG;
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_REG *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorLRI, commands.end());
|
||||
{
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_REG *>(*itorLRI);
|
||||
EXPECT_EQ(cmd->getDestinationRegisterAddress(), 0xf10u);
|
||||
EXPECT_EQ(cmd->getSourceRegisterAddress(), 0xaf0u);
|
||||
}
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
#include "fixtures/command_container_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using CommandEncodeStatesTest = Test<CommandEncodeStatesFixture>;
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, encodeCopySamplerState) {
|
||||
using SAMPLER_STATE = typename FamilyType::SAMPLER_STATE;
|
||||
uint32_t numSamplers = 1;
|
||||
SAMPLER_STATE samplerState;
|
||||
|
||||
auto dsh = cmdContainer->getIndirectHeap(HeapType::DYNAMIC_STATE);
|
||||
auto usedBefore = dsh->getUsed();
|
||||
auto samplerStateOffset = EncodeStates<FamilyType>::copySamplerState(dsh, 0, numSamplers, 0, &samplerState);
|
||||
|
||||
auto pSmplr = reinterpret_cast<SAMPLER_STATE *>(ptrOffset(dsh->getCpuBase(), samplerStateOffset));
|
||||
EXPECT_EQ(pSmplr->getIndirectStatePointer(), usedBefore);
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenCreatedSurfaceStateBufferWhenAllocationProvidedThenUseAllocationAsInput) {
|
||||
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
|
||||
using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE;
|
||||
using AUXILIARY_SURFACE_MODE = typename RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE;
|
||||
|
||||
void *stateBuffer = alignedMalloc(sizeof(RENDER_SURFACE_STATE), sizeof(RENDER_SURFACE_STATE));
|
||||
ASSERT_NE(nullptr, stateBuffer);
|
||||
RENDER_SURFACE_STATE *state = reinterpret_cast<RENDER_SURFACE_STATE *>(stateBuffer);
|
||||
|
||||
memset(stateBuffer, 0, sizeof(RENDER_SURFACE_STATE));
|
||||
|
||||
size_t size = 0x1000;
|
||||
SURFACE_STATE_BUFFER_LENGTH length;
|
||||
|
||||
void *cpuAddr = reinterpret_cast<void *>(0x4000);
|
||||
uint64_t gpuAddr = 0x4000u;
|
||||
size_t allocSize = size;
|
||||
length.Length = static_cast<uint32_t>(allocSize - 1);
|
||||
GraphicsAllocation allocation(0, GraphicsAllocation::AllocationType::UNKNOWN, cpuAddr, gpuAddr, 0u, allocSize, MemoryPool::MemoryNull);
|
||||
EncodeSurfaceState<FamilyType>::encodeBuffer(stateBuffer, reinterpret_cast<void *>(gpuAddr), allocSize, 1,
|
||||
RENDER_SURFACE_STATE::COHERENCY_TYPE_IA_COHERENT);
|
||||
EXPECT_EQ(length.SurfaceState.Depth + 1u, state->getDepth());
|
||||
EXPECT_EQ(length.SurfaceState.Width + 1u, state->getWidth());
|
||||
EXPECT_EQ(length.SurfaceState.Height + 1u, state->getHeight());
|
||||
EXPECT_EQ(gpuAddr, state->getSurfaceBaseAddress());
|
||||
|
||||
alignedFree(stateBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenCreatedSurfaceStateBufferWhenAllocationNotProvidedThenStateTypeIsNull) {
|
||||
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
|
||||
|
||||
void *stateBuffer = alignedMalloc(sizeof(RENDER_SURFACE_STATE), sizeof(RENDER_SURFACE_STATE));
|
||||
ASSERT_NE(nullptr, stateBuffer);
|
||||
RENDER_SURFACE_STATE *state = reinterpret_cast<RENDER_SURFACE_STATE *>(stateBuffer);
|
||||
|
||||
memset(stateBuffer, 0, sizeof(RENDER_SURFACE_STATE));
|
||||
|
||||
size_t size = 0x1000;
|
||||
SURFACE_STATE_BUFFER_LENGTH length;
|
||||
|
||||
uint64_t gpuAddr = 0;
|
||||
size_t allocSize = size;
|
||||
length.Length = static_cast<uint32_t>(allocSize - 1);
|
||||
|
||||
EncodeSurfaceState<FamilyType>::encodeBuffer(stateBuffer, reinterpret_cast<void *>(gpuAddr), allocSize, 1,
|
||||
RENDER_SURFACE_STATE::COHERENCY_TYPE_IA_COHERENT);
|
||||
|
||||
EXPECT_EQ(RENDER_SURFACE_STATE::SURFACE_TYPE_SURFTYPE_NULL, state->getSurfaceType());
|
||||
|
||||
alignedFree(stateBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenCreatedSurfaceStateBufferWhenGpuCoherencyProvidedThenCoherencyGpuIsSet) {
|
||||
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
|
||||
|
||||
void *stateBuffer = alignedMalloc(sizeof(RENDER_SURFACE_STATE), sizeof(RENDER_SURFACE_STATE));
|
||||
ASSERT_NE(nullptr, stateBuffer);
|
||||
RENDER_SURFACE_STATE *state = reinterpret_cast<RENDER_SURFACE_STATE *>(stateBuffer);
|
||||
|
||||
memset(stateBuffer, 0, sizeof(RENDER_SURFACE_STATE));
|
||||
|
||||
size_t size = 0x1000;
|
||||
SURFACE_STATE_BUFFER_LENGTH length;
|
||||
|
||||
uint64_t gpuAddr = 0;
|
||||
size_t allocSize = size;
|
||||
length.Length = static_cast<uint32_t>(allocSize - 1);
|
||||
|
||||
EncodeSurfaceState<FamilyType>::encodeBuffer(stateBuffer, reinterpret_cast<void *>(gpuAddr), allocSize, 1,
|
||||
RENDER_SURFACE_STATE::COHERENCY_TYPE_GPU_COHERENT);
|
||||
|
||||
EXPECT_EQ(RENDER_SURFACE_STATE::COHERENCY_TYPE_GPU_COHERENT, state->getCoherencyType());
|
||||
|
||||
alignedFree(stateBuffer);
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenCommandContainerWithDirtyHeapsWhenSetStateBaseAddressCalledThenStateBaseAddressAreNotSet) {
|
||||
using STATE_BASE_ADDRESS = typename FamilyType::STATE_BASE_ADDRESS;
|
||||
cmdContainer->dirtyHeaps = 0;
|
||||
auto baseAddres = cmdContainer->getCommandStream()->getCpuBase();
|
||||
|
||||
cmdContainer->setHeapDirty(NEO::HeapType::DYNAMIC_STATE);
|
||||
cmdContainer->setHeapDirty(NEO::HeapType::INDIRECT_OBJECT);
|
||||
cmdContainer->setHeapDirty(NEO::HeapType::SURFACE_STATE);
|
||||
|
||||
EncodeStateBaseAddress<FamilyType>::encode(*cmdContainer.get());
|
||||
|
||||
auto dsh = cmdContainer->getIndirectHeap(NEO::HeapType::DYNAMIC_STATE);
|
||||
auto ioh = cmdContainer->getIndirectHeap(NEO::HeapType::INDIRECT_OBJECT);
|
||||
auto ssh = cmdContainer->getIndirectHeap(NEO::HeapType::SURFACE_STATE);
|
||||
|
||||
auto pCmd = static_cast<STATE_BASE_ADDRESS *>(baseAddres);
|
||||
|
||||
EXPECT_EQ(dsh->getHeapGpuBase(), pCmd->getDynamicStateBaseAddress());
|
||||
EXPECT_EQ(ioh->getHeapGpuBase(), pCmd->getIndirectObjectBaseAddress());
|
||||
EXPECT_EQ(ssh->getHeapGpuBase(), pCmd->getSurfaceStateBaseAddress());
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenCommandContainerWhenSetStateBaseAddressCalledThenStateBaseAddressIsSetCorrectly) {
|
||||
using STATE_BASE_ADDRESS = typename FamilyType::STATE_BASE_ADDRESS;
|
||||
cmdContainer->dirtyHeaps = 0;
|
||||
|
||||
EncodeStateBaseAddress<FamilyType>::encode(*cmdContainer.get());
|
||||
|
||||
auto dsh = cmdContainer->getIndirectHeap(NEO::HeapType::DYNAMIC_STATE);
|
||||
auto ssh = cmdContainer->getIndirectHeap(NEO::HeapType::SURFACE_STATE);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer->getCommandStream()->getCpuBase(), 0), cmdContainer->getCommandStream()->getUsed());
|
||||
|
||||
auto itorCmd = find<STATE_BASE_ADDRESS *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorCmd, commands.end());
|
||||
|
||||
auto cmd = genCmdCast<STATE_BASE_ADDRESS *>(*itorCmd);
|
||||
|
||||
EXPECT_NE(dsh->getHeapGpuBase(), cmd->getDynamicStateBaseAddress());
|
||||
EXPECT_NE(ssh->getHeapGpuBase(), cmd->getSurfaceStateBaseAddress());
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenAnAlignedDstPtrThenNoAlignmentNorOffsetNeeded) {
|
||||
uintptr_t ptr = NEO::EncodeSurfaceState<FamilyType>::getSurfaceBaseAddressAlignment() << 1;
|
||||
size_t offset = 0;
|
||||
NEO::EncodeSurfaceState<FamilyType>::getSshAlignedPointer(ptr, offset);
|
||||
EXPECT_TRUE((ptr & (NEO::EncodeSurfaceState<FamilyType>::getSurfaceBaseAddressAlignment() - 1)) == 0x0u);
|
||||
EXPECT_EQ(0u, offset);
|
||||
}
|
||||
|
||||
HWTEST_F(CommandEncodeStatesTest, givenAnUnalignedDstPtrThenCorrectAlignedPtrAndOffsetAreCalculated) {
|
||||
uintptr_t ptr = NEO::EncodeSurfaceState<FamilyType>::getSurfaceBaseAddressAlignment() >> 1;
|
||||
size_t offset = 0;
|
||||
NEO::EncodeSurfaceState<FamilyType>::getSshAlignedPointer(ptr, offset);
|
||||
EXPECT_TRUE((ptr & (NEO::EncodeSurfaceState<FamilyType>::getSurfaceBaseAddressAlignment() - 1)) == 0x0u);
|
||||
EXPECT_NE(0u, offset);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_tests_fixtures
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/command_container_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/preemption_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/preemption_fixture.cpp
|
||||
)
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_tests_fixtures ${NEO_CORE_tests_fixtures})
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "shared/source/command_container/command_encoder.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "test.h"
|
||||
|
||||
class CommandEncodeStatesFixture : public DeviceFixture {
|
||||
public:
|
||||
class MyMockCommandContainer : public CommandContainer {
|
||||
public:
|
||||
using CommandContainer::dirtyHeaps;
|
||||
};
|
||||
|
||||
void SetUp() {
|
||||
DeviceFixture::SetUp();
|
||||
cmdContainer = std::make_unique<MyMockCommandContainer>();
|
||||
cmdContainer->initialize(pDevice);
|
||||
}
|
||||
void TearDown() {
|
||||
cmdContainer.reset();
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
std::unique_ptr<MyMockCommandContainer> cmdContainer;
|
||||
};
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fixtures/preemption_fixture.h"
|
||||
|
||||
#include "shared/source/command_stream/preemption.h"
|
||||
#include "shared/source/helpers/hw_info.h"
|
||||
#include "opencl/source/command_queue/enqueue_common.h"
|
||||
#include "opencl/source/command_queue/enqueue_kernel.h"
|
||||
#include "opencl/source/command_queue/enqueue_marker.h"
|
||||
#include "opencl/source/helpers/dispatch_info.h"
|
||||
#include "opencl/source/scheduler/scheduler_kernel.h"
|
||||
#include "opencl/test/unit_test/fixtures/hello_world_fixture.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_command_queue.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_context.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_device.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_kernel.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
DevicePreemptionTests::DevicePreemptionTests() = default;
|
||||
DevicePreemptionTests::~DevicePreemptionTests() = default;
|
||||
|
||||
void DevicePreemptionTests::SetUp() {
|
||||
if (dbgRestore == nullptr) {
|
||||
dbgRestore.reset(new DebugManagerStateRestore());
|
||||
}
|
||||
const cl_queue_properties properties[3] = {CL_QUEUE_PROPERTIES, 0, 0};
|
||||
kernelInfo = std::make_unique<KernelInfo>();
|
||||
device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
context.reset(new MockContext(device.get()));
|
||||
cmdQ.reset(new MockCommandQueue(context.get(), device.get(), properties));
|
||||
executionEnvironment.reset(new SPatchExecutionEnvironment);
|
||||
memset(executionEnvironment.get(), 0, sizeof(SPatchExecutionEnvironment));
|
||||
kernelInfo->patchInfo.executionEnvironment = executionEnvironment.get();
|
||||
program = std::make_unique<MockProgram>(*device->getExecutionEnvironment());
|
||||
kernel.reset(new MockKernel(program.get(), *kernelInfo, *device));
|
||||
dispatchInfo.reset(new DispatchInfo(kernel.get(), 1, Vec3<size_t>(1, 1, 1), Vec3<size_t>(1, 1, 1), Vec3<size_t>(0, 0, 0)));
|
||||
|
||||
ASSERT_NE(nullptr, device);
|
||||
ASSERT_NE(nullptr, context);
|
||||
ASSERT_NE(nullptr, cmdQ);
|
||||
|
||||
waTable = &device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable;
|
||||
}
|
||||
|
||||
void DevicePreemptionTests::TearDown() {
|
||||
dbgRestore.reset();
|
||||
kernel.reset();
|
||||
kernelInfo.reset();
|
||||
dispatchInfo.reset();
|
||||
cmdQ.reset();
|
||||
context.reset();
|
||||
device.reset();
|
||||
}
|
||||
|
||||
void ThreadGroupPreemptionEnqueueKernelTest::SetUp() {
|
||||
dbgRestore.reset(new DebugManagerStateRestore());
|
||||
DebugManager.flags.ForcePreemptionMode.set(static_cast<int32_t>(PreemptionMode::ThreadGroup));
|
||||
|
||||
globalHwInfo = const_cast<HardwareInfo *>(platformDevices[0]);
|
||||
originalPreemptionMode = globalHwInfo->capabilityTable.defaultPreemptionMode;
|
||||
globalHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::ThreadGroup;
|
||||
|
||||
HelloWorldFixture::SetUp();
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
}
|
||||
|
||||
void ThreadGroupPreemptionEnqueueKernelTest::TearDown() {
|
||||
globalHwInfo->capabilityTable.defaultPreemptionMode = originalPreemptionMode;
|
||||
|
||||
HelloWorldFixture::TearDown();
|
||||
}
|
||||
|
||||
void MidThreadPreemptionEnqueueKernelTest::SetUp() {
|
||||
dbgRestore.reset(new DebugManagerStateRestore());
|
||||
DebugManager.flags.ForcePreemptionMode.set(static_cast<int32_t>(PreemptionMode::MidThread));
|
||||
|
||||
globalHwInfo = const_cast<HardwareInfo *>(platformDevices[0]);
|
||||
originalPreemptionMode = globalHwInfo->capabilityTable.defaultPreemptionMode;
|
||||
globalHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::MidThread;
|
||||
|
||||
HelloWorldFixture::SetUp();
|
||||
pDevice->setPreemptionMode(PreemptionMode::MidThread);
|
||||
}
|
||||
|
||||
void MidThreadPreemptionEnqueueKernelTest::TearDown() {
|
||||
globalHwInfo->capabilityTable.defaultPreemptionMode = originalPreemptionMode;
|
||||
|
||||
HelloWorldFixture::TearDown();
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "opencl/test/unit_test/fixtures/hello_world_fixture.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace iOpenCL {
|
||||
struct SPatchExecutionEnvironment;
|
||||
}
|
||||
|
||||
namespace NEO {
|
||||
class DispatchInfo;
|
||||
class MockCommandQueue;
|
||||
class MockContext;
|
||||
class MockDevice;
|
||||
class MockKernel;
|
||||
class MockProgram;
|
||||
struct KernelInfo;
|
||||
struct WorkaroundTable;
|
||||
|
||||
using PreemptionEnqueueKernelFixture = HelloWorldFixture<HelloWorldFixtureFactory>;
|
||||
using PreemptionEnqueueKernelTest = Test<PreemptionEnqueueKernelFixture>;
|
||||
} // namespace NEO
|
||||
|
||||
class DevicePreemptionTests : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
DevicePreemptionTests();
|
||||
~DevicePreemptionTests() override;
|
||||
|
||||
NEO::PreemptionMode preemptionMode;
|
||||
NEO::WorkaroundTable *waTable = nullptr;
|
||||
std::unique_ptr<NEO::DispatchInfo> dispatchInfo;
|
||||
std::unique_ptr<NEO::MockKernel> kernel;
|
||||
std::unique_ptr<NEO::MockCommandQueue> cmdQ;
|
||||
std::unique_ptr<NEO::MockClDevice> device;
|
||||
std::unique_ptr<NEO::MockContext> context;
|
||||
std::unique_ptr<DebugManagerStateRestore> dbgRestore;
|
||||
std::unique_ptr<iOpenCL::SPatchExecutionEnvironment> executionEnvironment;
|
||||
std::unique_ptr<NEO::MockProgram> program;
|
||||
std::unique_ptr<NEO::KernelInfo> kernelInfo;
|
||||
};
|
||||
|
||||
struct ThreadGroupPreemptionEnqueueKernelTest : NEO::PreemptionEnqueueKernelTest {
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
NEO::HardwareInfo *globalHwInfo;
|
||||
NEO::PreemptionMode originalPreemptionMode;
|
||||
|
||||
std::unique_ptr<DebugManagerStateRestore> dbgRestore;
|
||||
};
|
||||
|
||||
struct MidThreadPreemptionEnqueueKernelTest : NEO::PreemptionEnqueueKernelTest {
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
NEO::HardwareInfo *globalHwInfo;
|
||||
NEO::PreemptionMode originalPreemptionMode;
|
||||
|
||||
std::unique_ptr<DebugManagerStateRestore> dbgRestore;
|
||||
};
|
||||
|
||||
struct PreemptionTestHwDetails {
|
||||
struct PreemptionModeHashT {
|
||||
auto operator()(const NEO::PreemptionMode &preemptionMode) const -> std::underlying_type<NEO::PreemptionMode>::type {
|
||||
return static_cast<std::underlying_type<NEO::PreemptionMode>::type>(preemptionMode);
|
||||
}
|
||||
};
|
||||
|
||||
bool supportsPreemptionProgramming() const {
|
||||
return modeToRegValueMap.size() > 0;
|
||||
}
|
||||
|
||||
uint32_t regAddress = 0;
|
||||
std::unordered_map<NEO::PreemptionMode, uint32_t, PreemptionModeHashT> modeToRegValueMap;
|
||||
uint32_t defaultRegValue = 0;
|
||||
};
|
||||
|
||||
template <typename FamilyType>
|
||||
PreemptionTestHwDetails GetPreemptionTestHwDetails();
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_TESTS_GEN11
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/image_surface_state_tests_gen11.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/preamble_tests_gen11.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/simd_helper_tests_gen11.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preamble_gen11.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preemption_gen11.cpp
|
||||
)
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_TESTS_GEN11 ${NEO_CORE_TESTS_GEN11})
|
||||
add_subdirectories()
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
using GenStruct = NEO::GEN11;
|
||||
using GenGfxFamily = NEO::ICLFamily;
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_base.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_base_mi_arb.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_gpgpu_walker.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_sip.inl"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.inl"
|
||||
|
||||
template <>
|
||||
size_t CmdParse<GenGfxFamily>::getCommandLengthHwSpecific(void *cmd) {
|
||||
{
|
||||
auto pCmd = genCmdCast<GPGPU_WALKER *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_VFE_STATE *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_STATE_FLUSH *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<STATE_SIP *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *CmdParse<GenGfxFamily>::getCommandNameHwSpecific(void *cmd) {
|
||||
if (nullptr != genCmdCast<GPGPU_WALKER *>(cmd)) {
|
||||
return "GPGPU_WALKER";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd)) {
|
||||
return "MEDIA_INTERFACE_DESCRIPTOR_LOAD";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_VFE_STATE *>(cmd)) {
|
||||
return "MEDIA_VFE_STATE";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_STATE_FLUSH *>(cmd)) {
|
||||
return "MEDIA_STATE_FLUSH";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(cmd)) {
|
||||
return "GPGPU_CSR_BASE_ADDRESS";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<STATE_SIP *>(cmd)) {
|
||||
return "STATE_SIP";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
template struct CmdParse<GenGfxFamily>;
|
||||
|
||||
namespace NEO {
|
||||
template void HardwareParse::findHardwareCommands<ICLFamily>();
|
||||
template void HardwareParse::findHardwareCommands<ICLFamily>(IndirectHeap *);
|
||||
template const void *HardwareParse::getStatelessArgumentPointer<ICLFamily>(const Kernel &kernel, uint32_t indexArg, IndirectHeap &ioh);
|
||||
} // namespace NEO
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "image/image_surface_state_fixture.h"
|
||||
|
||||
using ImageSurfaceStateTestsGen11 = ImageSurfaceStateTests;
|
||||
|
||||
GEN11TEST_F(ImageSurfaceStateTestsGen11, givenGmmWithMediaCompressedWhenSetFlagsForMediaCompressionThenAuxiliarySurfaceNoneIsSet) {
|
||||
auto size = sizeof(typename FamilyType::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename FamilyType::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
castSurfaceState->setAuxiliarySurfaceMode(FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = false;
|
||||
setFlagsForMediaCompression<FamilyType>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = true;
|
||||
setFlagsForMediaCompression<FamilyType>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_NONE);
|
||||
}
|
||||
|
||||
GEN11TEST_F(ImageSurfaceStateTestsGen11, givenGmmWithMediaCompressedWhenSetMipTailStartLodThenMipTailStartLodIsSet) {
|
||||
auto size = sizeof(typename FamilyType::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename FamilyType::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
|
||||
setMipTailStartLod<FamilyType>(castSurfaceState, nullptr);
|
||||
|
||||
EXPECT_EQ(castSurfaceState->getMipTailStartLod(), 0u);
|
||||
|
||||
setMipTailStartLod<FamilyType>(castSurfaceState, &mockGmm);
|
||||
|
||||
EXPECT_EQ(castSurfaceState->getMipTailStartLod(), mockGmm.gmmResourceInfo->getMipTailStartLodSurfaceState());
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "source_level_debugger/source_level_debugger_preamble_test.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace NEO;
|
||||
typedef ICLFamily GfxFamily;
|
||||
|
||||
#include "source_level_debugger/source_level_debugger_preamble_test.inl"
|
||||
|
||||
using PreambleTestGen11 = ::testing::Test;
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenMidThreadPreemptionAndDebuggingActiveWhenStateSipIsProgrammedThenCorrectSipKernelIsUsed) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDebuggingActiveWhenStateSipIsProgrammedThenCorrectSipKernelIsUsedTest();
|
||||
}
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenMidThreadPreemptionAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenPreemptionDisabledAndDebuggingActiveWhenPreambleIsProgrammedThenCorrectSipKernelIsUsed) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenPreemptionDisabledAndDebuggingActiveWhenPreambleIsProgrammedThenCorrectSipKernelIsUsedTest();
|
||||
}
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenPreemptionDisabledAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenPreemptionDisabledAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleIsProgrammedThenCorrectSipKernelIsUsed) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleIsProgrammedThenCorrectSipKernelIsUsedTest();
|
||||
}
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenDisabledPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenDisabledPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN11TEST_F(PreambleTestGen11, givenKernelDebuggingActiveAndDisabledPreemptionWhenGetAdditionalCommandsSizeIsCalledThen2MiLoadRegisterImmCmdsAndStateSipAreInlcuded) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenKernelDebuggingActiveAndDisabledPreemptionWhenGetAdditionalCommandsSizeIsCalledThen2MiLoadRegisterImmCmdsAreInlcudedTest();
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/simd_helper_tests.inl"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using TestSimdConfigSet = ::testing::Test;
|
||||
|
||||
GEN11TEST_F(TestSimdConfigSet, GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturnedGen11) {
|
||||
GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturned<typename FamilyType::GPGPU_WALKER>::TestBodyImpl();
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/preemption.h"
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "preamble/preamble_fixture.h"
|
||||
|
||||
#include "reg_configs_common.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
typedef PreambleFixture IclSlm;
|
||||
|
||||
GEN11TEST_F(IclSlm, shouldBeEnabledOnGen11) {
|
||||
typedef ICLFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
LinearStream &cs = linearStream;
|
||||
uint32_t l3Config = PreambleHelper<FamilyType>::getL3Config(**platformDevices, true);
|
||||
PreambleHelper<FamilyType>::programL3(&cs, l3Config);
|
||||
|
||||
parseCommands<ICLFamily>(cs);
|
||||
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorLRI);
|
||||
|
||||
const auto &lri = *reinterpret_cast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
auto RegisterOffset = L3CNTLRegisterOffset<FamilyType>::registerOffset;
|
||||
EXPECT_EQ(RegisterOffset, lri.getRegisterOffset());
|
||||
EXPECT_EQ(0u, lri.getDataDword() & 1);
|
||||
}
|
||||
|
||||
GEN11TEST_F(IclSlm, givenGen11WhenProgramingL3ThenErrorDetectionBehaviorControlBitSet) {
|
||||
uint32_t l3Config = PreambleHelper<FamilyType>::getL3Config(**platformDevices, true);
|
||||
|
||||
uint32_t errorDetectionBehaviorControlBit = 1 << 9;
|
||||
|
||||
EXPECT_TRUE((l3Config & errorDetectionBehaviorControlBit) != 0);
|
||||
}
|
||||
|
||||
GEN11TEST_F(IclSlm, givenGen11IsL3Programing) {
|
||||
bool isL3Programmable =
|
||||
PreambleHelper<FamilyType>::isL3Configurable(**platformDevices);
|
||||
|
||||
EXPECT_FALSE(isL3Programmable);
|
||||
}
|
||||
|
||||
typedef PreambleFixture Gen11UrbEntryAllocationSize;
|
||||
GEN11TEST_F(Gen11UrbEntryAllocationSize, getUrbEntryAllocationSize) {
|
||||
uint32_t actualVal = PreambleHelper<FamilyType>::getUrbEntryAllocationSize();
|
||||
EXPECT_EQ(0x782u, actualVal);
|
||||
}
|
||||
|
||||
typedef PreambleVfeState Gen11PreambleVfeState;
|
||||
GEN11TEST_F(Gen11PreambleVfeState, WaOff) {
|
||||
typedef typename ICLFamily::PIPE_CONTROL PIPE_CONTROL;
|
||||
testWaTable->waSendMIFLUSHBeforeVFE = 0;
|
||||
LinearStream &cs = linearStream;
|
||||
PreambleHelper<ICLFamily>::programVFEState(&linearStream, pPlatform->getDevice(0)->getHardwareInfo(), 0, 0, 168u, aub_stream::EngineType::ENGINE_RCS);
|
||||
|
||||
parseCommands<ICLFamily>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_FALSE(pc.getRenderTargetCacheFlushEnable());
|
||||
EXPECT_FALSE(pc.getDepthCacheFlushEnable());
|
||||
EXPECT_FALSE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
|
||||
GEN11TEST_F(Gen11PreambleVfeState, WaOn) {
|
||||
typedef typename ICLFamily::PIPE_CONTROL PIPE_CONTROL;
|
||||
testWaTable->waSendMIFLUSHBeforeVFE = 1;
|
||||
LinearStream &cs = linearStream;
|
||||
PreambleHelper<ICLFamily>::programVFEState(&linearStream, pPlatform->getDevice(0)->getHardwareInfo(), 0, 0, 168u, aub_stream::EngineType::ENGINE_RCS);
|
||||
|
||||
parseCommands<ICLFamily>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_TRUE(pc.getRenderTargetCacheFlushEnable());
|
||||
EXPECT_TRUE(pc.getDepthCacheFlushEnable());
|
||||
EXPECT_TRUE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
|
||||
typedef PreambleFixture PreemptionWatermarkGen11;
|
||||
GEN11TEST_F(PreemptionWatermarkGen11, givenPreambleThenPreambleWorkAroundsIsNotProgrammed) {
|
||||
PreambleHelper<FamilyType>::programGenSpecificPreambleWorkArounds(&linearStream, **platformDevices);
|
||||
|
||||
parseCommands<FamilyType>(linearStream);
|
||||
|
||||
auto cmd = findMmioCmd<FamilyType>(cmdList.begin(), cmdList.end(), FfSliceCsChknReg2::address);
|
||||
ASSERT_EQ(nullptr, cmd);
|
||||
|
||||
MockDevice mockDevice;
|
||||
mockDevice.setDebuggerActive(false);
|
||||
size_t expectedSize = PreemptionHelper::getRequiredPreambleSize<FamilyType>(mockDevice);
|
||||
EXPECT_EQ(expectedSize, PreambleHelper<FamilyType>::getAdditionalCommandsSize(mockDevice));
|
||||
|
||||
mockDevice.setDebuggerActive(true);
|
||||
expectedSize += PreambleHelper<FamilyType>::getKernelDebuggingCommandsSize(mockDevice.isDebuggerActive());
|
||||
EXPECT_EQ(expectedSize, PreambleHelper<FamilyType>::getAdditionalCommandsSize(mockDevice));
|
||||
}
|
||||
|
||||
typedef PreambleFixture ThreadArbitrationGen11;
|
||||
GEN11TEST_F(ThreadArbitrationGen11, givenPreambleWhenItIsProgrammedThenThreadArbitrationIsSet) {
|
||||
DebugManagerStateRestore dbgRestore;
|
||||
DebugManager.flags.ForcePreemptionMode.set(static_cast<int32_t>(PreemptionMode::Disabled));
|
||||
typedef ICLFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
typedef ICLFamily::PIPE_CONTROL PIPE_CONTROL;
|
||||
LinearStream &cs = linearStream;
|
||||
uint32_t l3Config = PreambleHelper<FamilyType>::getL3Config(**platformDevices, true);
|
||||
MockDevice mockDevice;
|
||||
PreambleHelper<FamilyType>::programPreamble(&linearStream, mockDevice, l3Config,
|
||||
ThreadArbitrationPolicy::RoundRobin,
|
||||
nullptr, nullptr);
|
||||
|
||||
parseCommands<FamilyType>(cs);
|
||||
|
||||
auto ppC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(ppC, cmdList.end());
|
||||
|
||||
auto cmd = findMmioCmd<FamilyType>(cmdList.begin(), cmdList.end(), RowChickenReg4::address);
|
||||
ASSERT_NE(nullptr, cmd);
|
||||
|
||||
EXPECT_EQ(RowChickenReg4::regDataForArbitrationPolicy[ThreadArbitrationPolicy::RoundRobin], cmd->getDataDword());
|
||||
|
||||
MockDevice device;
|
||||
EXPECT_EQ(0u, PreambleHelper<ICLFamily>::getAdditionalCommandsSize(device));
|
||||
EXPECT_EQ(sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL), PreambleHelper<ICLFamily>::getThreadArbitrationCommandsSize());
|
||||
}
|
||||
|
||||
GEN11TEST_F(ThreadArbitrationGen11, defaultArbitrationPolicy) {
|
||||
EXPECT_EQ(ThreadArbitrationPolicy::RoundRobinAfterDependency, PreambleHelper<ICLFamily>::getDefaultThreadArbitrationPolicy());
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/hw_helper.h"
|
||||
#include "fixtures/preemption_fixture.h"
|
||||
#include "opencl/source/built_ins/built_ins.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_buffer.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_command_queue.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_csr.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using Gen11PreemptionTests = DevicePreemptionTests;
|
||||
|
||||
template <>
|
||||
PreemptionTestHwDetails GetPreemptionTestHwDetails<ICLFamily>() {
|
||||
PreemptionTestHwDetails ret;
|
||||
ret.modeToRegValueMap[PreemptionMode::ThreadGroup] = DwordBuilder::build(1, true) | DwordBuilder::build(2, true, false);
|
||||
ret.modeToRegValueMap[PreemptionMode::MidBatch] = DwordBuilder::build(2, true) | DwordBuilder::build(1, true, false);
|
||||
ret.modeToRegValueMap[PreemptionMode::MidThread] = DwordBuilder::build(2, true, false) | DwordBuilder::build(1, true, false);
|
||||
ret.defaultRegValue = ret.modeToRegValueMap[PreemptionMode::MidBatch];
|
||||
ret.regAddress = 0x2580u;
|
||||
return ret;
|
||||
}
|
||||
|
||||
GEN11TEST_F(Gen11PreemptionTests, whenMidThreadPreemptionIsNotAvailableThenDoesNotProgramStateSip) {
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
|
||||
size_t requiredSize = PreemptionHelper::getRequiredPreambleSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(0U, requiredSize);
|
||||
|
||||
LinearStream cmdStream{nullptr, 0};
|
||||
PreemptionHelper::getRequiredStateSipCmdSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(0U, cmdStream.getUsed());
|
||||
}
|
||||
|
||||
GEN11TEST_F(Gen11PreemptionTests, whenMidThreadPreemptionIsAvailableThenStateSipIsProgrammed) {
|
||||
using STATE_SIP = typename FamilyType::STATE_SIP;
|
||||
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
executionEnvironment->DisableMidThreadPreemption = 0;
|
||||
|
||||
size_t requiredCmdStreamSize = PreemptionHelper::getRequiredStateSipCmdSize<FamilyType>(device->getDevice());
|
||||
size_t expectedPreambleSize = sizeof(STATE_SIP);
|
||||
EXPECT_EQ(expectedPreambleSize, requiredCmdStreamSize);
|
||||
|
||||
StackVec<char, 8192> streamStorage(requiredCmdStreamSize);
|
||||
ASSERT_LE(requiredCmdStreamSize, streamStorage.size());
|
||||
|
||||
LinearStream cmdStream{streamStorage.begin(), streamStorage.size()};
|
||||
PreemptionHelper::programStateSip<FamilyType>(cmdStream, device->getDevice());
|
||||
|
||||
HardwareParse hwParsePreamble;
|
||||
hwParsePreamble.parseCommands<FamilyType>(cmdStream);
|
||||
|
||||
auto stateSipCmd = hwParsePreamble.getCommand<STATE_SIP>();
|
||||
ASSERT_NE(nullptr, stateSipCmd);
|
||||
EXPECT_EQ(device->getExecutionEnvironment()->getBuiltIns()->getSipKernel(SipKernelType::Csr, device->getDevice()).getSipAllocation()->getGpuAddressToPatch(), stateSipCmd->getSystemInstructionPointer());
|
||||
}
|
||||
|
||||
GEN11TEST_F(Gen11PreemptionTests, getRequiredCmdQSize) {
|
||||
size_t expectedSize = 0;
|
||||
EXPECT_EQ(expectedSize, PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice()));
|
||||
}
|
||||
|
||||
GEN11TEST_F(Gen11PreemptionTests, applyPreemptionWaCmds) {
|
||||
size_t usedSize = 0;
|
||||
auto &cmdStream = cmdQ->getCS(0);
|
||||
|
||||
PreemptionHelper::applyPreemptionWaCmdsBegin<FamilyType>(&cmdStream, device->getDevice());
|
||||
EXPECT_EQ(usedSize, cmdStream.getUsed());
|
||||
PreemptionHelper::applyPreemptionWaCmdsEnd<FamilyType>(&cmdStream, device->getDevice());
|
||||
EXPECT_EQ(usedSize, cmdStream.getUsed());
|
||||
}
|
||||
|
||||
GEN11TEST_F(Gen11PreemptionTests, givenInterfaceDescriptorDataWhenMidThreadPreemptionModeThenSetDisableThreadPreemptionBitToDisable) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
|
||||
INTERFACE_DESCRIPTOR_DATA iddArg;
|
||||
iddArg = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidThread);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE, iddArg.getThreadPreemptionDisable());
|
||||
}
|
||||
|
||||
GEN11TEST_F(Gen11PreemptionTests, givenInterfaceDescriptorDataWhenNoMidThreadPreemptionModeThenSetDisableThreadPreemptionBitToEnable) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
|
||||
INTERFACE_DESCRIPTOR_DATA iddArg;
|
||||
iddArg = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::Disabled);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE, iddArg.getThreadPreemptionDisable());
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidBatch);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE, iddArg.getThreadPreemptionDisable());
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::ThreadGroup);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE, iddArg.getThreadPreemptionDisable());
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_TESTS_GEN12LP
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/image_surface_state_tests_gen12lp.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/simd_helper_tests_gen12lp.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preamble_gen12lp.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_command_encoder_gen12lp.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preemption_gen12lp.inl
|
||||
)
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_TESTS_GEN12LP ${NEO_CORE_TESTS_GEN12LP})
|
||||
add_subdirectories()
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
size_t getAdditionalCommandLengthHwSpecific(void *cmd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *getAdditionalCommandNameHwSpecific(void *cmd) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
using GenStruct = NEO::GEN12LP;
|
||||
using GenGfxFamily = NEO::TGLLPFamily;
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_base.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_compute_mode.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_gpgpu_walker.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_mi_arb.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_sip.inl"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.inl"
|
||||
|
||||
#include "cmd_parse_gen12lp.inl"
|
||||
|
||||
template <>
|
||||
size_t CmdParse<GenGfxFamily>::getCommandLengthHwSpecific(void *cmd) {
|
||||
{
|
||||
auto pCmd = genCmdCast<GPGPU_WALKER *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_VFE_STATE *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_STATE_FLUSH *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<STATE_COMPUTE_MODE *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<STATE_SIP *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
|
||||
return getAdditionalCommandLengthHwSpecific(cmd);
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *CmdParse<GenGfxFamily>::getCommandNameHwSpecific(void *cmd) {
|
||||
if (nullptr != genCmdCast<GPGPU_WALKER *>(cmd)) {
|
||||
return "GPGPU_WALKER";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd)) {
|
||||
return "MEDIA_INTERFACE_DESCRIPTOR_LOAD";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_VFE_STATE *>(cmd)) {
|
||||
return "MEDIA_VFE_STATE";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_STATE_FLUSH *>(cmd)) {
|
||||
return "MEDIA_STATE_FLUSH";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<STATE_COMPUTE_MODE *>(cmd)) {
|
||||
return "MEDIA_STATE_FLUSH";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(cmd)) {
|
||||
return "GPGPU_CSR_BASE_ADDRESS";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<STATE_SIP *>(cmd)) {
|
||||
return "STATE_SIP";
|
||||
}
|
||||
|
||||
return getAdditionalCommandNameHwSpecific(cmd);
|
||||
}
|
||||
|
||||
template struct CmdParse<GenGfxFamily>;
|
||||
|
||||
namespace NEO {
|
||||
template void HardwareParse::findHardwareCommands<TGLLPFamily>();
|
||||
template void HardwareParse::findHardwareCommands<TGLLPFamily>(IndirectHeap *);
|
||||
template const void *HardwareParse::getStatelessArgumentPointer<TGLLPFamily>(const Kernel &kernel, uint32_t indexArg, IndirectHeap &ioh);
|
||||
} // namespace NEO
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "image/image_surface_state_fixture.h"
|
||||
|
||||
using ImageSurfaceStateTestsGen12LP = ImageSurfaceStateTests;
|
||||
|
||||
GEN12LPTEST_F(ImageSurfaceStateTestsGen12LP, givenGmmWithMediaCompressedWhenSetFlagsForMediaCompressionThenAuxiliarySurfaceNoneIsSetAndMemoryCompressionEnable) {
|
||||
auto size = sizeof(typename TGLLPFamily::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename TGLLPFamily::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
castSurfaceState->setAuxiliarySurfaceMode(TGLLPFamily::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = false;
|
||||
setFlagsForMediaCompression<TGLLPFamily>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), TGLLPFamily::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
EXPECT_EQ(castSurfaceState->getMemoryCompressionEnable(), false);
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = true;
|
||||
setFlagsForMediaCompression<TGLLPFamily>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), TGLLPFamily::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_NONE);
|
||||
EXPECT_EQ(castSurfaceState->getMemoryCompressionEnable(), true);
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(ImageSurfaceStateTestsGen12LP, givenGmmWhenSetClearColorParamsThenClearValueAddressEnable) {
|
||||
auto size = sizeof(typename TGLLPFamily::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename TGLLPFamily::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Gpu.IndirectClearColor = true;
|
||||
setClearColorParams<TGLLPFamily>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getClearValueAddressEnable(), true);
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(ImageSurfaceStateTestsGen12LP, givenGmmWithMediaCompressedWhenSetMipTailStartLodThenMipTailStartLodIsSet) {
|
||||
auto size = sizeof(typename FamilyType::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename FamilyType::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
|
||||
setMipTailStartLod<FamilyType>(castSurfaceState, nullptr);
|
||||
|
||||
EXPECT_EQ(castSurfaceState->getMipTailStartLod(), 0u);
|
||||
|
||||
setMipTailStartLod<FamilyType>(castSurfaceState, &mockGmm);
|
||||
|
||||
EXPECT_EQ(castSurfaceState->getMipTailStartLod(), mockGmm.gmmResourceInfo->getMipTailStartLodSurfaceState());
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/simd_helper_tests.inl"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using TestSimdConfigSet = ::testing::Test;
|
||||
|
||||
GEN12LPTEST_F(TestSimdConfigSet, GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturnedGen12LP) {
|
||||
GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturned<typename FamilyType::GPGPU_WALKER>::TestBodyImpl();
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_container/cmdcontainer.h"
|
||||
#include "shared/source/command_container/command_encoder.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "reg_configs_common.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using CommandEncoderTest = Test<DeviceFixture>;
|
||||
|
||||
GEN12LPTEST_F(CommandEncoderTest, givenAdjustStateComputeModeStateComputeModeShowsNonCoherencySet) {
|
||||
using STATE_COMPUTE_MODE = typename FamilyType::STATE_COMPUTE_MODE;
|
||||
using FORCE_NON_COHERENT = typename STATE_COMPUTE_MODE::FORCE_NON_COHERENT;
|
||||
|
||||
CommandContainer cmdContainer;
|
||||
|
||||
bool ret = cmdContainer.initialize(pDevice);
|
||||
ASSERT_TRUE(ret);
|
||||
|
||||
auto usedSpaceBefore = cmdContainer.getCommandStream()->getUsed();
|
||||
|
||||
// Adjust the State Compute Mode which sets FORCE_NON_COHERENT_FORCE_GPU_NON_COHERENT
|
||||
EncodeStates<FamilyType>::adjustStateComputeMode(cmdContainer);
|
||||
|
||||
auto usedSpaceAfter = cmdContainer.getCommandStream()->getUsed();
|
||||
ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
|
||||
|
||||
auto expectedCmdSize = sizeof(STATE_COMPUTE_MODE);
|
||||
auto cmdAddedSize = usedSpaceAfter - usedSpaceBefore;
|
||||
EXPECT_EQ(expectedCmdSize, cmdAddedSize);
|
||||
|
||||
auto expectedScmCmd = FamilyType::cmdInitStateComputeMode;
|
||||
expectedScmCmd.setForceNonCoherent(FORCE_NON_COHERENT::FORCE_NON_COHERENT_FORCE_GPU_NON_COHERENT);
|
||||
expectedScmCmd.setMaskBits(FamilyType::stateComputeModeForceNonCoherentMask);
|
||||
|
||||
auto scmCmd = reinterpret_cast<STATE_COMPUTE_MODE *>(ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), usedSpaceBefore));
|
||||
EXPECT_TRUE(memcmp(&expectedScmCmd, scmCmd, sizeof(STATE_COMPUTE_MODE)) == 0);
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(CommandEncoderTest, givenCommandContainerWhenEncodeL3StateThenSetCorrectMMIO) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeL3State<FamilyType>::encode(cmdContainer, false);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorLRI, commands.end());
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
EXPECT_EQ(cmd->getRegisterOffset(), 0xB134u);
|
||||
EXPECT_EQ(cmd->getDataDword(), 0xD0000020u);
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/preemption.h"
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "preamble/preamble_fixture.h"
|
||||
|
||||
#include "reg_configs_common.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
typedef PreambleFixture TglLpSlm;
|
||||
|
||||
TGLLPTEST_F(TglLpSlm, givenTglLpWhenPreambleIsBeingProgrammedThenThreadArbitrationPolicyIsIgnored) {
|
||||
typedef TGLLPFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
LinearStream &cs = linearStream;
|
||||
uint32_t l3Config = PreambleHelper<TGLLPFamily>::getL3Config(pDevice->getHardwareInfo(), true);
|
||||
MockDevice mockDevice;
|
||||
PreambleHelper<TGLLPFamily>::programPreamble(&linearStream, mockDevice, l3Config,
|
||||
ThreadArbitrationPolicy::RoundRobin,
|
||||
nullptr, nullptr);
|
||||
|
||||
parseCommands<TGLLPFamily>(cs);
|
||||
|
||||
// parse through commands and ensure that 0xE404 is not being programmed
|
||||
EXPECT_EQ(0U, countMmio<FamilyType>(cmdList.begin(), cmdList.end(), 0xE404));
|
||||
}
|
||||
|
||||
TGLLPTEST_F(TglLpSlm, givenTglLpIsL3Programing) {
|
||||
bool isL3Programmable =
|
||||
PreambleHelper<TGLLPFamily>::isL3Configurable(**platformDevices);
|
||||
|
||||
EXPECT_FALSE(isL3Programmable);
|
||||
}
|
||||
|
||||
TGLLPTEST_F(TglLpSlm, shouldNotBeEnabledOnGen12) {
|
||||
typedef TGLLPFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
LinearStream &cs = linearStream;
|
||||
uint32_t l3Config = PreambleHelper<FamilyType>::getL3Config(pDevice->getHardwareInfo(), true);
|
||||
PreambleHelper<FamilyType>::programL3(&cs, l3Config);
|
||||
|
||||
parseCommands<TGLLPFamily>(cs);
|
||||
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_EQ(cmdList.end(), itorLRI);
|
||||
}
|
||||
|
||||
typedef PreambleFixture Gen12LpUrbEntryAllocationSize;
|
||||
TGLLPTEST_F(Gen12LpUrbEntryAllocationSize, getUrbEntryAllocationSize) {
|
||||
uint32_t actualVal = PreambleHelper<FamilyType>::getUrbEntryAllocationSize();
|
||||
EXPECT_EQ(1024u, actualVal);
|
||||
}
|
||||
|
||||
typedef PreambleVfeState Gen12LpPreambleVfeState;
|
||||
TGLLPTEST_F(Gen12LpPreambleVfeState, WaOff) {
|
||||
typedef typename FamilyType::PIPE_CONTROL PIPE_CONTROL;
|
||||
testWaTable->waSendMIFLUSHBeforeVFE = 0;
|
||||
LinearStream &cs = linearStream;
|
||||
PreambleHelper<FamilyType>::programVFEState(&linearStream, pPlatform->getDevice(0)->getHardwareInfo(), 0, 0, 672u, aub_stream::EngineType::ENGINE_RCS);
|
||||
|
||||
parseCommands<FamilyType>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_FALSE(pc.getRenderTargetCacheFlushEnable());
|
||||
EXPECT_FALSE(pc.getDepthCacheFlushEnable());
|
||||
EXPECT_FALSE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
|
||||
TGLLPTEST_F(Gen12LpPreambleVfeState, givenCcsEngineWhenWaIsSetThenAppropriatePipeControlFlushesAreSet) {
|
||||
typedef typename FamilyType::PIPE_CONTROL PIPE_CONTROL;
|
||||
testWaTable->waSendMIFLUSHBeforeVFE = 1;
|
||||
LinearStream &cs = linearStream;
|
||||
|
||||
PreambleHelper<FamilyType>::programVFEState(&linearStream, pPlatform->getDevice(0)->getHardwareInfo(), 0, 0, 672u, aub_stream::EngineType::ENGINE_CCS);
|
||||
|
||||
parseCommands<FamilyType>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_FALSE(pc.getRenderTargetCacheFlushEnable());
|
||||
EXPECT_FALSE(pc.getDepthCacheFlushEnable());
|
||||
EXPECT_TRUE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
|
||||
TGLLPTEST_F(Gen12LpPreambleVfeState, givenRcsEngineWhenWaIsSetThenAppropriatePipeControlFlushesAreSet) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
testWaTable->waSendMIFLUSHBeforeVFE = 1;
|
||||
LinearStream &cs = linearStream;
|
||||
|
||||
PreambleHelper<FamilyType>::programVFEState(&linearStream, pPlatform->getDevice(0)->getHardwareInfo(), 0, 0, 672u, aub_stream::EngineType::ENGINE_RCS);
|
||||
|
||||
parseCommands<FamilyType>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_TRUE(pc.getRenderTargetCacheFlushEnable());
|
||||
EXPECT_TRUE(pc.getDepthCacheFlushEnable());
|
||||
EXPECT_TRUE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
|
||||
TGLLPTEST_F(Gen12LpPreambleVfeState, givenDefaultPipeControlWhenItIsProgrammedThenCsStallBitIsSet) {
|
||||
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
|
||||
|
||||
PIPE_CONTROL *pipeControl = static_cast<PIPE_CONTROL *>(linearStream.getSpace(sizeof(PIPE_CONTROL)));
|
||||
*pipeControl = FamilyType::cmdInitPipeControl;
|
||||
|
||||
EXPECT_EQ(1u, pipeControl->getCommandStreamerStallEnable());
|
||||
}
|
||||
|
||||
TGLLPTEST_F(Gen12LpPreambleVfeState, givenCfeFusedEuDispatchFlagsWhenprogramAdditionalFieldsInVfeStateIsCalledThenGetDisableSlice0Subslice2ReturnsCorrectValues) {
|
||||
using MEDIA_VFE_STATE = typename FamilyType::MEDIA_VFE_STATE;
|
||||
|
||||
DebugManagerStateRestore restorer;
|
||||
auto pHwInfo = pPlatform->getDevice(0)->getExecutionEnvironment()->getMutableHardwareInfo();
|
||||
auto pMediaVfeState = reinterpret_cast<MEDIA_VFE_STATE *>(linearStream.getSpace(sizeof(MEDIA_VFE_STATE)));
|
||||
*pMediaVfeState = FamilyType::cmdInitMediaVfeState;
|
||||
auto &waTable = pHwInfo->workaroundTable;
|
||||
|
||||
const std::array<std::tuple<bool, bool, int32_t>, 6> testParams{{std::make_tuple(false, false, 0),
|
||||
std::make_tuple(false, true, 0),
|
||||
std::make_tuple(false, false, -1),
|
||||
std::make_tuple(true, false, 1),
|
||||
std::make_tuple(true, true, -1),
|
||||
std::make_tuple(true, true, 1)}};
|
||||
|
||||
for (const auto ¶ms : testParams) {
|
||||
bool expectedValue, waDisableFusedThreadScheduling;
|
||||
int32_t debugKeyValue;
|
||||
std::tie(expectedValue, waDisableFusedThreadScheduling, debugKeyValue) = params;
|
||||
|
||||
waTable.waDisableFusedThreadScheduling = waDisableFusedThreadScheduling;
|
||||
::DebugManager.flags.CFEFusedEUDispatch.set(debugKeyValue);
|
||||
PreambleHelper<FamilyType>::programAdditionalFieldsInVfeState(pMediaVfeState, *pHwInfo);
|
||||
EXPECT_EQ(expectedValue, pMediaVfeState->getDisableSlice0Subslice2());
|
||||
}
|
||||
}
|
||||
|
||||
typedef PreambleFixture ThreadArbitrationGen12Lp;
|
||||
GEN12LPTEST_F(ThreadArbitrationGen12Lp, givenPolicyWhenThreadArbitrationProgrammedThenDoNothing) {
|
||||
LinearStream &cs = linearStream;
|
||||
|
||||
PreambleHelper<FamilyType>::programThreadArbitration(&cs, ThreadArbitrationPolicy::RoundRobin);
|
||||
|
||||
EXPECT_EQ(0u, cs.getUsed());
|
||||
EXPECT_EQ(0u, PreambleHelper<FamilyType>::getDefaultThreadArbitrationPolicy());
|
||||
}
|
||||
|
||||
typedef PreambleFixture PreemptionWatermarkGen12LP;
|
||||
GEN12LPTEST_F(PreemptionWatermarkGen12LP, givenPreambleThenPreambleWorkAroundsIsNotProgrammed) {
|
||||
PreambleHelper<FamilyType>::programGenSpecificPreambleWorkArounds(&linearStream, pDevice->getHardwareInfo());
|
||||
|
||||
parseCommands<FamilyType>(linearStream);
|
||||
|
||||
auto cmd = findMmioCmd<FamilyType>(cmdList.begin(), cmdList.end(), FfSliceCsChknReg2::address);
|
||||
ASSERT_EQ(nullptr, cmd);
|
||||
|
||||
MockDevice mockDevice;
|
||||
mockDevice.setDebuggerActive(false);
|
||||
size_t expectedSize = PreemptionHelper::getRequiredPreambleSize<FamilyType>(mockDevice);
|
||||
EXPECT_EQ(expectedSize, PreambleHelper<FamilyType>::getAdditionalCommandsSize(mockDevice));
|
||||
|
||||
mockDevice.setDebuggerActive(true);
|
||||
expectedSize += PreambleHelper<FamilyType>::getKernelDebuggingCommandsSize(mockDevice.isDebuggerActive());
|
||||
EXPECT_EQ(expectedSize, PreambleHelper<FamilyType>::getAdditionalCommandsSize(mockDevice));
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fixtures/preemption_fixture.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_buffer.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_command_queue.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_csr.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using Gen12LpPreemptionTests = DevicePreemptionTests;
|
||||
|
||||
template <>
|
||||
PreemptionTestHwDetails GetPreemptionTestHwDetails<TGLLPFamily>() {
|
||||
PreemptionTestHwDetails ret;
|
||||
ret.modeToRegValueMap[PreemptionMode::ThreadGroup] = DwordBuilder::build(1, true) | DwordBuilder::build(2, true, false);
|
||||
ret.modeToRegValueMap[PreemptionMode::MidBatch] = DwordBuilder::build(2, true) | DwordBuilder::build(1, true, false);
|
||||
ret.modeToRegValueMap[PreemptionMode::MidThread] = DwordBuilder::build(2, true, false) | DwordBuilder::build(1, true, false);
|
||||
ret.defaultRegValue = ret.modeToRegValueMap[PreemptionMode::MidBatch];
|
||||
ret.regAddress = 0x2580u;
|
||||
return ret;
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(Gen12LpPreemptionTests, whenProgramStateSipIsCalledThenStateSipCmdIsNotAddedToStream) {
|
||||
size_t requiredSize = PreemptionHelper::getRequiredStateSipCmdSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(0U, requiredSize);
|
||||
|
||||
LinearStream cmdStream{nullptr, 0};
|
||||
PreemptionHelper::programStateSip<FamilyType>(cmdStream, device->getDevice());
|
||||
EXPECT_EQ(0U, cmdStream.getUsed());
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(Gen12LpPreemptionTests, getRequiredCmdQSize) {
|
||||
size_t expectedSize = 0;
|
||||
EXPECT_EQ(expectedSize, PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice()));
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(Gen12LpPreemptionTests, applyPreemptionWaCmds) {
|
||||
size_t usedSize = 0;
|
||||
auto &cmdStream = cmdQ->getCS(0);
|
||||
|
||||
PreemptionHelper::applyPreemptionWaCmdsBegin<FamilyType>(&cmdStream, device->getDevice());
|
||||
EXPECT_EQ(usedSize, cmdStream.getUsed());
|
||||
PreemptionHelper::applyPreemptionWaCmdsEnd<FamilyType>(&cmdStream, device->getDevice());
|
||||
EXPECT_EQ(usedSize, cmdStream.getUsed());
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(Gen12LpPreemptionTests, givenInterfaceDescriptorDataWhenMidThreadPreemptionModeThenSetDisableThreadPreemptionBitToDisable) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
|
||||
INTERFACE_DESCRIPTOR_DATA iddArg;
|
||||
iddArg = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidThread);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE, iddArg.getThreadPreemptionDisable());
|
||||
}
|
||||
|
||||
GEN12LPTEST_F(Gen12LpPreemptionTests, givenInterfaceDescriptorDataWhenNoMidThreadPreemptionModeThenSetDisableThreadPreemptionBitToEnable) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
|
||||
INTERFACE_DESCRIPTOR_DATA iddArg;
|
||||
iddArg = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::Disabled);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE, iddArg.getThreadPreemptionDisable());
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidBatch);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE, iddArg.getThreadPreemptionDisable());
|
||||
|
||||
iddArg.setThreadPreemptionDisable(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_DISABLE);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::ThreadGroup);
|
||||
EXPECT_EQ(INTERFACE_DESCRIPTOR_DATA::THREAD_PREEMPTION_DISABLE_ENABLE, iddArg.getThreadPreemptionDisable());
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_TESTS_GEN8
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/image_surface_state_tests_gen8.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/simd_helper_tests_gen8.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preamble_gen8.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preemption_gen8.cpp
|
||||
)
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_TESTS_GEN8 ${NEO_CORE_TESTS_GEN8})
|
||||
add_subdirectories()
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
using GenStruct = NEO::GEN8;
|
||||
using GenGfxFamily = NEO::BDWFamily;
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_base.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_base_mi_arb.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_gpgpu_walker.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_sip.inl"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.inl"
|
||||
|
||||
template <>
|
||||
size_t CmdParse<GenGfxFamily>::getCommandLengthHwSpecific(void *cmd) {
|
||||
{
|
||||
auto pCmd = genCmdCast<GPGPU_WALKER *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_VFE_STATE *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_STATE_FLUSH *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *CmdParse<GenGfxFamily>::getCommandNameHwSpecific(void *cmd) {
|
||||
if (nullptr != genCmdCast<GPGPU_WALKER *>(cmd)) {
|
||||
return "GPGPU_WALKER";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd)) {
|
||||
return "MEDIA_INTERFACE_DESCRIPTOR_LOAD";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_VFE_STATE *>(cmd)) {
|
||||
return "MEDIA_VFE_STATE";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_STATE_FLUSH *>(cmd)) {
|
||||
return "MEDIA_STATE_FLUSH";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
template struct CmdParse<GenGfxFamily>;
|
||||
|
||||
namespace NEO {
|
||||
template void HardwareParse::findHardwareCommands<BDWFamily>();
|
||||
template void HardwareParse::findHardwareCommands<BDWFamily>(IndirectHeap *);
|
||||
template const void *HardwareParse::getStatelessArgumentPointer<BDWFamily>(const Kernel &kernel, uint32_t indexArg, IndirectHeap &ioh);
|
||||
} // namespace NEO
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "image/image_surface_state_fixture.h"
|
||||
|
||||
using ImageSurfaceStateTestsGen8 = ImageSurfaceStateTests;
|
||||
|
||||
GEN8TEST_F(ImageSurfaceStateTestsGen8, givenGmmWithMediaCompressedWhenSetFlagsForMediaCompressionThenAuxiliarySurfaceNoneIsSet) {
|
||||
auto size = sizeof(typename FamilyType::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename FamilyType::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
castSurfaceState->setAuxiliarySurfaceMode(FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = false;
|
||||
setFlagsForMediaCompression<FamilyType>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = true;
|
||||
setFlagsForMediaCompression<FamilyType>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_NONE);
|
||||
}
|
||||
|
||||
GEN8TEST_F(ImageSurfaceStateTestsGen8, givenGmmWithMediaCompressedWhenSetMipTailStartLodThenMipTailStartLodIsSet) {
|
||||
auto size = sizeof(typename FamilyType::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename FamilyType::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
|
||||
setMipTailStartLod<FamilyType>(castSurfaceState, nullptr);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/simd_helper_tests.inl"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using TestSimdConfigSet = ::testing::Test;
|
||||
|
||||
GEN8TEST_F(TestSimdConfigSet, GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturnedGen8) {
|
||||
GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturned<typename FamilyType::GPGPU_WALKER>::TestBodyImpl();
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/thread_arbitration_policy.h"
|
||||
#include "shared/source/helpers/preamble.h"
|
||||
#include "preamble/preamble_fixture.h"
|
||||
#include "opencl/source/gen8/reg_configs.h"
|
||||
#include "opencl/test/unit_test/fixtures/platform_fixture.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
typedef PreambleFixture BdwSlm;
|
||||
|
||||
BDWTEST_F(BdwSlm, shouldBeEnabledOnGen8) {
|
||||
typedef BDWFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
LinearStream &cs = linearStream;
|
||||
uint32_t l3Config = PreambleHelper<BDWFamily>::getL3Config(**platformDevices, true);
|
||||
PreambleHelper<BDWFamily>::programL3(&cs, l3Config);
|
||||
|
||||
parseCommands<BDWFamily>(cs);
|
||||
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorLRI);
|
||||
|
||||
const auto &lri = *reinterpret_cast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
auto RegisterOffset = L3CNTLRegisterOffset<BDWFamily>::registerOffset;
|
||||
EXPECT_EQ(RegisterOffset, lri.getRegisterOffset());
|
||||
EXPECT_EQ(1u, lri.getDataDword() & 1);
|
||||
}
|
||||
|
||||
typedef PreambleFixture Gen8L3Config;
|
||||
|
||||
BDWTEST_F(Gen8L3Config, checkNoSLM) {
|
||||
bool slmUsed = false;
|
||||
uint32_t l3Config = 0;
|
||||
|
||||
l3Config = getL3ConfigHelper<IGFX_BROADWELL>(slmUsed);
|
||||
EXPECT_EQ(0x80000340u, l3Config);
|
||||
|
||||
uint32_t errorDetectionBehaviorControlBit = 1 << 9;
|
||||
EXPECT_TRUE((l3Config & errorDetectionBehaviorControlBit) != 0);
|
||||
}
|
||||
|
||||
BDWTEST_F(Gen8L3Config, checkSLM) {
|
||||
bool slmUsed = true;
|
||||
uint32_t l3Config = 0;
|
||||
|
||||
l3Config = getL3ConfigHelper<IGFX_BROADWELL>(slmUsed);
|
||||
EXPECT_EQ(0x60000321u, l3Config);
|
||||
|
||||
uint32_t errorDetectionBehaviorControlBit = 1 << 9;
|
||||
EXPECT_TRUE((l3Config & errorDetectionBehaviorControlBit) != 0);
|
||||
}
|
||||
|
||||
BDWTEST_F(Gen8L3Config, givenGen8IsL3Programing) {
|
||||
bool l3ConfigDifference;
|
||||
bool isL3Programmable;
|
||||
|
||||
l3ConfigDifference =
|
||||
PreambleHelper<BDWFamily>::getL3Config(**platformDevices, true) !=
|
||||
PreambleHelper<BDWFamily>::getL3Config(**platformDevices, false);
|
||||
isL3Programmable =
|
||||
PreambleHelper<BDWFamily>::isL3Configurable(**platformDevices);
|
||||
|
||||
EXPECT_EQ(l3ConfigDifference, isL3Programmable);
|
||||
}
|
||||
|
||||
typedef PreambleFixture ThreadArbitrationGen8;
|
||||
BDWTEST_F(ThreadArbitrationGen8, givenPolicyWhenThreadArbitrationProgrammedThenDoNothing) {
|
||||
typedef BDWFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
LinearStream &cs = linearStream;
|
||||
|
||||
PreambleHelper<BDWFamily>::programThreadArbitration(&cs, ThreadArbitrationPolicy::RoundRobin);
|
||||
|
||||
EXPECT_EQ(0u, cs.getUsed());
|
||||
|
||||
MockDevice device;
|
||||
EXPECT_EQ(0u, PreambleHelper<BDWFamily>::getAdditionalCommandsSize(device));
|
||||
EXPECT_EQ(0u, PreambleHelper<BDWFamily>::getThreadArbitrationCommandsSize());
|
||||
EXPECT_EQ(0u, PreambleHelper<BDWFamily>::getDefaultThreadArbitrationPolicy());
|
||||
}
|
||||
|
||||
typedef PreambleFixture Gen8UrbEntryAllocationSize;
|
||||
BDWTEST_F(Gen8UrbEntryAllocationSize, getUrbEntryAllocationSize) {
|
||||
uint32_t actualVal = PreambleHelper<FamilyType>::getUrbEntryAllocationSize();
|
||||
EXPECT_EQ(0x782u, actualVal);
|
||||
}
|
||||
|
||||
BDWTEST_F(PreambleVfeState, basic) {
|
||||
typedef BDWFamily::PIPE_CONTROL PIPE_CONTROL;
|
||||
|
||||
LinearStream &cs = linearStream;
|
||||
PreambleHelper<BDWFamily>::programVFEState(&linearStream, **platformDevices, 0, 0, 168u, aub_stream::EngineType::ENGINE_RCS);
|
||||
|
||||
parseCommands<BDWFamily>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_TRUE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/linear_stream.h"
|
||||
#include "shared/source/command_stream/preemption.h"
|
||||
#include "shared/source/helpers/hw_helper.h"
|
||||
#include "shared/source/memory_manager/memory_constants.h"
|
||||
#include "fixtures/preemption_fixture.h"
|
||||
#include "opencl/test/unit_test/command_queue/enqueue_fixture.h"
|
||||
#include "opencl/test/unit_test/fixtures/hello_world_fixture.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_buffer.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_command_queue.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_csr.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_submissions_aggregator.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using Gen8PreemptionTests = DevicePreemptionTests;
|
||||
using Gen8PreemptionEnqueueKernelTest = PreemptionEnqueueKernelTest;
|
||||
|
||||
template <>
|
||||
PreemptionTestHwDetails GetPreemptionTestHwDetails<BDWFamily>() {
|
||||
PreemptionTestHwDetails ret;
|
||||
ret.modeToRegValueMap[PreemptionMode::ThreadGroup] = 0;
|
||||
ret.modeToRegValueMap[PreemptionMode::MidBatch] = (1 << 2);
|
||||
ret.defaultRegValue = ret.modeToRegValueMap[PreemptionMode::MidBatch];
|
||||
ret.regAddress = 0x2248u;
|
||||
return ret;
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, allowThreadGroupPreemptionReturnsTrue) {
|
||||
PreemptionFlags flags = {};
|
||||
PreemptionHelper::setPreemptionLevelFlags(flags, device->getDevice(), kernel.get());
|
||||
EXPECT_TRUE(PreemptionHelper::allowThreadGroupPreemption(flags));
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, whenProgramStateSipIsCalledThenNoCmdsAreProgrammed) {
|
||||
size_t requiredSize = PreemptionHelper::getRequiredStateSipCmdSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(0U, requiredSize);
|
||||
|
||||
LinearStream cmdStream{nullptr, 0};
|
||||
PreemptionHelper::programStateSip<FamilyType>(cmdStream, device->getDevice());
|
||||
EXPECT_EQ(0U, cmdStream.getUsed());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogram) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
|
||||
csr.getMemoryManager()->setForce32BitAllocations(false);
|
||||
csr.setMediaVFEStateDirty(false);
|
||||
size_t off[3] = {0, 0, 0};
|
||||
size_t gws[3] = {1, 1, 1};
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
|
||||
HardwareParse hwParser;
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwParser.parseCommands<FamilyType>(csr.commandStream);
|
||||
auto offset = csr.commandStream.getUsed();
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
pCmdQ->flush();
|
||||
hwParser.parseCommands<FamilyType>(csr.commandStream, offset);
|
||||
|
||||
size_t numMmiosFound = countMmio<FamilyType>(hwParser.cmdList.begin(), hwParser.cmdList.end(), 0x2248u);
|
||||
EXPECT_EQ(1U, numMmiosFound);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionEnqueueKernelTest, givenValidKernelForPreemptionWhenEnqueueKernelCalledThenPassDevicePreemptionMode) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
auto mockCsr = new MockCsrHw2<FamilyType>(*pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
pDevice->resetCommandStreamReceiver(mockCsr);
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
PreemptionFlags flags = {};
|
||||
MultiDispatchInfo multiDispatch(mockKernel.mockKernel);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, PreemptionHelper::taskPreemptionMode(*pDevice, multiDispatch));
|
||||
|
||||
size_t gws[3] = {1, 0, 0};
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, nullptr, gws, nullptr, 0, nullptr, nullptr);
|
||||
pCmdQ->flush();
|
||||
|
||||
EXPECT_EQ(1, mockCsr->flushCalledCount);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, mockCsr->passedDispatchFlags.preemptionMode);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionEnqueueKernelTest, givenValidKernelForPreemptionWhenEnqueueKernelCalledAndBlockedThenPassDevicePreemptionMode) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
auto mockCsr = new MockCsrHw2<FamilyType>(*pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
pDevice->resetCommandStreamReceiver(mockCsr);
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
PreemptionFlags flags = {};
|
||||
PreemptionHelper::setPreemptionLevelFlags(flags, *pDevice, mockKernel.mockKernel);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, PreemptionHelper::taskPreemptionMode(pDevice->getPreemptionMode(), flags));
|
||||
|
||||
UserEvent userEventObj;
|
||||
cl_event userEvent = &userEventObj;
|
||||
size_t gws[3] = {1, 0, 0};
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, nullptr, gws, nullptr, 1, &userEvent, nullptr);
|
||||
pCmdQ->flush();
|
||||
EXPECT_EQ(0, mockCsr->flushCalledCount);
|
||||
|
||||
userEventObj.setStatus(CL_COMPLETE);
|
||||
pCmdQ->flush();
|
||||
EXPECT_EQ(1, mockCsr->flushCalledCount);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, mockCsr->passedDispatchFlags.preemptionMode);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionEnqueueKernelTest, givenDisabledPreemptionWhenEnqueueKernelCalledThenPassDisabledPreemptionMode) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::Disabled);
|
||||
auto mockCsr = new MockCsrHw2<FamilyType>(*pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
pDevice->resetCommandStreamReceiver(mockCsr);
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
PreemptionFlags flags = {};
|
||||
PreemptionHelper::setPreemptionLevelFlags(flags, *pDevice, mockKernel.mockKernel);
|
||||
EXPECT_EQ(PreemptionMode::Disabled, PreemptionHelper::taskPreemptionMode(pDevice->getPreemptionMode(), flags));
|
||||
|
||||
size_t gws[3] = {1, 0, 0};
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, nullptr, gws, nullptr, 0, nullptr, nullptr);
|
||||
pCmdQ->flush();
|
||||
|
||||
EXPECT_EQ(1, mockCsr->flushCalledCount);
|
||||
EXPECT_EQ(PreemptionMode::Disabled, mockCsr->passedDispatchFlags.preemptionMode);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, getPreemptionWaCsSizeMidBatch) {
|
||||
size_t expectedSize = 0;
|
||||
device->setPreemptionMode(PreemptionMode::MidBatch);
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, getPreemptionWaCsSizeThreadGroupNoWa) {
|
||||
size_t expectedSize = 0;
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, getPreemptionWaCsSizeThreadGroupWa) {
|
||||
typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
size_t expectedSize = 2 * sizeof(MI_LOAD_REGISTER_IMM);
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, getPreemptionWaCsSizeMidThreadNoWa) {
|
||||
size_t expectedSize = 0;
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, getPreemptionWaCsSizeMidThreadWa) {
|
||||
typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
size_t expectedSize = 2 * sizeof(MI_LOAD_REGISTER_IMM);
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTests, givenInterfaceDescriptorDataWhenAnyPreemptionModeThenNoChange) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
|
||||
INTERFACE_DESCRIPTOR_DATA idd;
|
||||
INTERFACE_DESCRIPTOR_DATA iddArg;
|
||||
int ret;
|
||||
|
||||
idd = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
iddArg = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::Disabled);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidBatch);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::ThreadGroup);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidThread);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
struct Gen8PreemptionTestsLinearStream : public Gen8PreemptionTests {
|
||||
void SetUp() override {
|
||||
Gen8PreemptionTests::SetUp();
|
||||
cmdBufferAllocation = alignedMalloc(MemoryConstants::pageSize, MemoryConstants::pageSize);
|
||||
cmdBuffer.replaceBuffer(cmdBufferAllocation, MemoryConstants::pageSize);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
alignedFree(cmdBufferAllocation);
|
||||
Gen8PreemptionTests::TearDown();
|
||||
}
|
||||
|
||||
LinearStream cmdBuffer;
|
||||
void *cmdBufferAllocation;
|
||||
HardwareParse cmdBufferParser;
|
||||
};
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenMidBatchPreemptionWhenProgrammingWaCmdsBeginThenExpectNoCmds) {
|
||||
device->setPreemptionMode(PreemptionMode::MidBatch);
|
||||
PreemptionHelper::applyPreemptionWaCmdsBegin<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenMidBatchPreemptionWhenProgrammingWaCmdsEndThenExpectNoCmds) {
|
||||
device->setPreemptionMode(PreemptionMode::MidBatch);
|
||||
PreemptionHelper::applyPreemptionWaCmdsEnd<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenThreadGroupPreemptionNoWaSetWhenProgrammingWaCmdsBeginThenExpectNoCmd) {
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
PreemptionHelper::applyPreemptionWaCmdsBegin<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenThreadGroupPreemptionNoWaSetWhenProgrammingWaCmdsEndThenExpectNoCmd) {
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
PreemptionHelper::applyPreemptionWaCmdsEnd<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenThreadGroupPreemptionWaSetWhenProgrammingWaCmdsBeginThenExpectMmioCmd) {
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
PreemptionHelper::applyPreemptionWaCmdsBegin<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
|
||||
cmdBufferParser.parseCommands<FamilyType>(cmdBuffer);
|
||||
cmdBufferParser.findHardwareCommands<FamilyType>();
|
||||
GenCmdList::iterator itMmioCmd = cmdBufferParser.lriList.begin();
|
||||
ASSERT_NE(cmdBufferParser.lriList.end(), itMmioCmd);
|
||||
MI_LOAD_REGISTER_IMM *mmioCmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itMmioCmd);
|
||||
EXPECT_EQ(0x2600u, mmioCmd->getRegisterOffset());
|
||||
EXPECT_EQ(0xFFFFFFFFu, mmioCmd->getDataDword());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenThreadGroupPreemptionWaSetWhenProgrammingWaCmdsEndThenExpectMmioCmd) {
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
PreemptionHelper::applyPreemptionWaCmdsEnd<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
|
||||
cmdBufferParser.parseCommands<FamilyType>(cmdBuffer);
|
||||
cmdBufferParser.findHardwareCommands<FamilyType>();
|
||||
GenCmdList::iterator itMmioCmd = cmdBufferParser.lriList.begin();
|
||||
ASSERT_NE(cmdBufferParser.lriList.end(), itMmioCmd);
|
||||
MI_LOAD_REGISTER_IMM *mmioCmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itMmioCmd);
|
||||
EXPECT_EQ(0x2600u, mmioCmd->getRegisterOffset());
|
||||
EXPECT_EQ(0x00000000u, mmioCmd->getDataDword());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenMidThreadPreemptionNoWaSetWhenProgrammingWaCmdsBeginThenExpectNoCmd) {
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
PreemptionHelper::applyPreemptionWaCmdsBegin<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenMidThreadPreemptionNoWaSetWhenProgrammingWaCmdsEndThenExpectNoCmd) {
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
PreemptionHelper::applyPreemptionWaCmdsEnd<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
EXPECT_EQ(0u, cmdBuffer.getUsed());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenMidThreadPreemptionWaSetWhenProgrammingWaCmdsBeginThenExpectMmioCmd) {
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
PreemptionHelper::applyPreemptionWaCmdsBegin<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
|
||||
cmdBufferParser.parseCommands<FamilyType>(cmdBuffer);
|
||||
cmdBufferParser.findHardwareCommands<FamilyType>();
|
||||
GenCmdList::iterator itMmioCmd = cmdBufferParser.lriList.begin();
|
||||
ASSERT_NE(cmdBufferParser.lriList.end(), itMmioCmd);
|
||||
MI_LOAD_REGISTER_IMM *mmioCmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itMmioCmd);
|
||||
EXPECT_EQ(0x2600u, mmioCmd->getRegisterOffset());
|
||||
EXPECT_EQ(0xFFFFFFFFu, mmioCmd->getDataDword());
|
||||
}
|
||||
|
||||
GEN8TEST_F(Gen8PreemptionTestsLinearStream, givenMidThreadPreemptionWaSetWhenProgrammingWaCmdsEndThenExpectMmioCmd) {
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
PreemptionHelper::applyPreemptionWaCmdsEnd<FamilyType>(&cmdBuffer, device->getDevice());
|
||||
|
||||
cmdBufferParser.parseCommands<FamilyType>(cmdBuffer);
|
||||
cmdBufferParser.findHardwareCommands<FamilyType>();
|
||||
GenCmdList::iterator itMmioCmd = cmdBufferParser.lriList.begin();
|
||||
ASSERT_NE(cmdBufferParser.lriList.end(), itMmioCmd);
|
||||
MI_LOAD_REGISTER_IMM *mmioCmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itMmioCmd);
|
||||
EXPECT_EQ(0x2600u, mmioCmd->getRegisterOffset());
|
||||
EXPECT_EQ(0x00000000u, mmioCmd->getDataDword());
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_TESTS_GEN9
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/image_surface_state_tests_gen9.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/preamble_tests_gen9.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/simd_helper_tests_gen9.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_command_encoder_gen9.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preemption_gen9.cpp
|
||||
)
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_TESTS_GEN9 ${NEO_CORE_TESTS_GEN9})
|
||||
add_subdirectories()
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
using GenStruct = NEO::GEN9;
|
||||
using GenGfxFamily = NEO::SKLFamily;
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_base.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_base_mi_arb.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_gpgpu_walker.inl"
|
||||
#include "opencl/test/unit_test/gen_common/cmd_parse_sip.inl"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.inl"
|
||||
|
||||
template <>
|
||||
size_t CmdParse<GenGfxFamily>::getCommandLengthHwSpecific(void *cmd) {
|
||||
{
|
||||
auto pCmd = genCmdCast<GPGPU_WALKER *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_VFE_STATE *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<MEDIA_STATE_FLUSH *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
{
|
||||
auto pCmd = genCmdCast<STATE_SIP *>(cmd);
|
||||
if (pCmd)
|
||||
return pCmd->TheStructure.Common.DwordLength + 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *CmdParse<GenGfxFamily>::getCommandNameHwSpecific(void *cmd) {
|
||||
if (nullptr != genCmdCast<GPGPU_WALKER *>(cmd)) {
|
||||
return "GPGPU_WALKER";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_INTERFACE_DESCRIPTOR_LOAD *>(cmd)) {
|
||||
return "MEDIA_INTERFACE_DESCRIPTOR_LOAD";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_VFE_STATE *>(cmd)) {
|
||||
return "MEDIA_VFE_STATE";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<MEDIA_STATE_FLUSH *>(cmd)) {
|
||||
return "MEDIA_STATE_FLUSH";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(cmd)) {
|
||||
return "GPGPU_CSR_BASE_ADDRESS";
|
||||
}
|
||||
|
||||
if (nullptr != genCmdCast<STATE_SIP *>(cmd)) {
|
||||
return "STATE_SIP";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
template struct CmdParse<GenGfxFamily>;
|
||||
|
||||
namespace NEO {
|
||||
template void HardwareParse::findHardwareCommands<SKLFamily>();
|
||||
template void HardwareParse::findHardwareCommands<SKLFamily>(IndirectHeap *);
|
||||
template const void *HardwareParse::getStatelessArgumentPointer<SKLFamily>(const Kernel &kernel, uint32_t indexArg, IndirectHeap &ioh);
|
||||
} // namespace NEO
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "image/image_surface_state_fixture.h"
|
||||
|
||||
using ImageSurfaceStateTestsGen9 = ImageSurfaceStateTests;
|
||||
|
||||
GEN9TEST_F(ImageSurfaceStateTestsGen9, givenGmmWithMediaCompressedWhenSetFlagsForMediaCompressionThenAuxiliarySurfaceNoneIsSet) {
|
||||
auto size = sizeof(typename FamilyType::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename FamilyType::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
castSurfaceState->setAuxiliarySurfaceMode(FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = false;
|
||||
setFlagsForMediaCompression<FamilyType>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_CCS_E);
|
||||
mockGmm.gmmResourceInfo->getResourceFlags()->Info.MediaCompressed = true;
|
||||
setFlagsForMediaCompression<FamilyType>(castSurfaceState, &mockGmm);
|
||||
EXPECT_EQ(castSurfaceState->getAuxiliarySurfaceMode(), FamilyType::RENDER_SURFACE_STATE::AUXILIARY_SURFACE_MODE::AUXILIARY_SURFACE_MODE_AUX_NONE);
|
||||
}
|
||||
|
||||
GEN9TEST_F(ImageSurfaceStateTestsGen9, givenGmmWithMediaCompressedWhenSetMipTailStartLodThenMipTailStartLodIsSet) {
|
||||
auto size = sizeof(typename FamilyType::RENDER_SURFACE_STATE);
|
||||
auto surfaceState = std::make_unique<char[]>(size);
|
||||
auto castSurfaceState = reinterpret_cast<typename FamilyType::RENDER_SURFACE_STATE *>(surfaceState.get());
|
||||
|
||||
setMipTailStartLod<FamilyType>(castSurfaceState, nullptr);
|
||||
|
||||
EXPECT_EQ(castSurfaceState->getMipTailStartLod(), 0u);
|
||||
|
||||
setMipTailStartLod<FamilyType>(castSurfaceState, &mockGmm);
|
||||
|
||||
EXPECT_EQ(castSurfaceState->getMipTailStartLod(), mockGmm.gmmResourceInfo->getMipTailStartLodSurfaceState());
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "source_level_debugger/source_level_debugger_preamble_test.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace NEO;
|
||||
typedef SKLFamily GfxFamily;
|
||||
|
||||
#include "source_level_debugger/source_level_debugger_preamble_test.inl"
|
||||
|
||||
using PreambleTestGen9 = ::testing::Test;
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenMidThreadPreemptionAndDebuggingActiveWhenStateSipIsProgrammedThenCorrectSipKernelIsUsed) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDebuggingActiveWhenStateSipIsProgrammedThenCorrectSipKernelIsUsedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenMidThreadPreemptionAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenPreemptionDisabledAndDebuggingActiveWhenPreambleIsProgrammedThenCorrectSipKernelIsUsed) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenPreemptionDisabledAndDebuggingActiveWhenPreambleIsProgrammedThenCorrectSipKernelIsUsedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenPreemptionDisabledAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenPreemptionDisabledAndDebuggingActiveWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleIsProgrammedThenCorrectSipKernelIsUsed) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleIsProgrammedThenCorrectSipKernelIsUsedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenMidThreadPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenDisabledPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenDisabledPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenKernelDebuggingActiveAndDisabledPreemptionWhenGetAdditionalCommandsSizeIsCalledThen2MiLoadRegisterImmCmdsAreInlcuded) {
|
||||
SourceLevelDebuggerPreambleTest<FamilyType>::givenKernelDebuggingActiveAndDisabledPreemptionWhenGetAdditionalCommandsSizeIsCalledThen2MiLoadRegisterImmCmdsAreInlcudedTest();
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleTestGen9, givenGen9IsL3Programing) {
|
||||
bool l3ConfigDifference;
|
||||
bool isL3Programmable;
|
||||
|
||||
l3ConfigDifference =
|
||||
PreambleHelper<FamilyType>::getL3Config(**platformDevices, true) !=
|
||||
PreambleHelper<FamilyType>::getL3Config(**platformDevices, false);
|
||||
isL3Programmable =
|
||||
PreambleHelper<FamilyType>::isL3Configurable(**platformDevices);
|
||||
|
||||
EXPECT_EQ(l3ConfigDifference, isL3Programmable);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/simd_helper_tests.inl"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using TestSimdConfigSet = ::testing::Test;
|
||||
|
||||
GEN9TEST_F(TestSimdConfigSet, GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturnedGen9) {
|
||||
GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturned<typename FamilyType::GPGPU_WALKER>::TestBodyImpl();
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_TESTS_GEN9_SKL
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_preamble_skl.cpp
|
||||
)
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_TESTS_GEN9_SKL ${NEO_CORE_TESTS_GEN9_SKL})
|
||||
add_subdirectories()
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/preemption.h"
|
||||
#include "shared/source/command_stream/thread_arbitration_policy.h"
|
||||
#include "shared/source/helpers/preamble.h"
|
||||
#include "helpers/debug_manager_state_restore.h"
|
||||
#include "preamble/preamble_fixture.h"
|
||||
#include "opencl/source/gen9/reg_configs.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
typedef PreambleFixture SklSlm;
|
||||
|
||||
SKLTEST_F(SklSlm, shouldBeEnabledOnGen9) {
|
||||
typedef SKLFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
LinearStream &cs = linearStream;
|
||||
uint32_t l3Config = PreambleHelper<FamilyType>::getL3Config(**platformDevices, true);
|
||||
|
||||
PreambleHelper<SKLFamily>::programL3(&cs, l3Config);
|
||||
|
||||
parseCommands<SKLFamily>(cs);
|
||||
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorLRI);
|
||||
|
||||
const auto &lri = *reinterpret_cast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
auto RegisterOffset = L3CNTLRegisterOffset<FamilyType>::registerOffset;
|
||||
EXPECT_EQ(RegisterOffset, lri.getRegisterOffset());
|
||||
EXPECT_EQ(1u, lri.getDataDword() & 1);
|
||||
}
|
||||
|
||||
typedef PreambleFixture Gen9L3Config;
|
||||
|
||||
SKLTEST_F(Gen9L3Config, checkNoSLM) {
|
||||
bool slmUsed = false;
|
||||
uint32_t l3Config = 0;
|
||||
|
||||
l3Config = getL3ConfigHelper<IGFX_SKYLAKE>(slmUsed);
|
||||
EXPECT_EQ(0x80000340u, l3Config);
|
||||
|
||||
uint32_t errorDetectionBehaviorControlBit = 1 << 9;
|
||||
EXPECT_TRUE((l3Config & errorDetectionBehaviorControlBit) != 0);
|
||||
|
||||
l3Config = getL3ConfigHelper<IGFX_BROXTON>(slmUsed);
|
||||
EXPECT_EQ(0x80000340u, l3Config);
|
||||
|
||||
EXPECT_TRUE((l3Config & errorDetectionBehaviorControlBit) != 0);
|
||||
}
|
||||
|
||||
SKLTEST_F(Gen9L3Config, checkSLM) {
|
||||
bool slmUsed = true;
|
||||
uint32_t l3Config = 0;
|
||||
|
||||
l3Config = getL3ConfigHelper<IGFX_SKYLAKE>(slmUsed);
|
||||
EXPECT_EQ(0x60000321u, l3Config);
|
||||
|
||||
uint32_t errorDetectionBehaviorControlBit = 1 << 9;
|
||||
EXPECT_TRUE((l3Config & errorDetectionBehaviorControlBit) != 0);
|
||||
|
||||
l3Config = getL3ConfigHelper<IGFX_BROXTON>(slmUsed);
|
||||
EXPECT_EQ(0x60000321u, l3Config);
|
||||
|
||||
EXPECT_TRUE((l3Config & errorDetectionBehaviorControlBit) != 0);
|
||||
}
|
||||
|
||||
typedef PreambleFixture ThreadArbitration;
|
||||
SKLTEST_F(ThreadArbitration, givenPreambleWhenItIsProgrammedThenThreadArbitrationIsSetToRoundRobin) {
|
||||
DebugManagerStateRestore dbgRestore;
|
||||
DebugManager.flags.ForcePreemptionMode.set(static_cast<int32_t>(PreemptionMode::Disabled));
|
||||
typedef SKLFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
typedef SKLFamily::PIPE_CONTROL PIPE_CONTROL;
|
||||
LinearStream &cs = linearStream;
|
||||
uint32_t l3Config = PreambleHelper<FamilyType>::getL3Config(**platformDevices, true);
|
||||
MockDevice mockDevice;
|
||||
PreambleHelper<SKLFamily>::programPreamble(&linearStream, mockDevice, l3Config,
|
||||
ThreadArbitrationPolicy::RoundRobin,
|
||||
nullptr, nullptr);
|
||||
|
||||
parseCommands<SKLFamily>(cs);
|
||||
|
||||
auto ppC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(ppC, cmdList.end());
|
||||
|
||||
auto itorLRI = reverse_find<MI_LOAD_REGISTER_IMM *>(cmdList.rbegin(), cmdList.rend());
|
||||
ASSERT_NE(cmdList.rend(), itorLRI);
|
||||
|
||||
const auto &lri = *reinterpret_cast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
EXPECT_EQ(0xE404u, lri.getRegisterOffset());
|
||||
EXPECT_EQ(0x100u, lri.getDataDword());
|
||||
|
||||
MockDevice device;
|
||||
EXPECT_EQ(0u, PreambleHelper<SKLFamily>::getAdditionalCommandsSize(device));
|
||||
EXPECT_EQ(sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL), PreambleHelper<SKLFamily>::getThreadArbitrationCommandsSize());
|
||||
}
|
||||
|
||||
SKLTEST_F(ThreadArbitration, defaultArbitrationPolicy) {
|
||||
EXPECT_EQ(ThreadArbitrationPolicy::RoundRobin, PreambleHelper<SKLFamily>::getDefaultThreadArbitrationPolicy());
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleVfeState, WaOff) {
|
||||
typedef typename FamilyType::PIPE_CONTROL PIPE_CONTROL;
|
||||
testWaTable->waSendMIFLUSHBeforeVFE = 0;
|
||||
LinearStream &cs = linearStream;
|
||||
PreambleHelper<FamilyType>::programVFEState(&linearStream, pPlatform->getDevice(0)->getHardwareInfo(), 0, 0, 168u, aub_stream::EngineType::ENGINE_RCS);
|
||||
|
||||
parseCommands<FamilyType>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_FALSE(pc.getRenderTargetCacheFlushEnable());
|
||||
EXPECT_FALSE(pc.getDepthCacheFlushEnable());
|
||||
EXPECT_FALSE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
|
||||
GEN9TEST_F(PreambleVfeState, WaOn) {
|
||||
typedef typename FamilyType::PIPE_CONTROL PIPE_CONTROL;
|
||||
testWaTable->waSendMIFLUSHBeforeVFE = 1;
|
||||
LinearStream &cs = linearStream;
|
||||
PreambleHelper<FamilyType>::programVFEState(&linearStream, pPlatform->getDevice(0)->getHardwareInfo(), 0, 0, 168u, aub_stream::EngineType::ENGINE_RCS);
|
||||
|
||||
parseCommands<FamilyType>(cs);
|
||||
|
||||
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
|
||||
ASSERT_NE(cmdList.end(), itorPC);
|
||||
|
||||
const auto &pc = *reinterpret_cast<PIPE_CONTROL *>(*itorPC);
|
||||
EXPECT_TRUE(pc.getRenderTargetCacheFlushEnable());
|
||||
EXPECT_TRUE(pc.getDepthCacheFlushEnable());
|
||||
EXPECT_TRUE(pc.getDcFlushEnable());
|
||||
EXPECT_EQ(1u, pc.getCommandStreamerStallEnable());
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_container/cmdcontainer.h"
|
||||
#include "shared/source/command_container/command_encoder.h"
|
||||
#include "opencl/test/unit_test/fixtures/device_fixture.h"
|
||||
#include "opencl/test/unit_test/gen_common/gen_cmd_parse.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "reg_configs_common.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using CommandEncoderTest = Test<DeviceFixture>;
|
||||
|
||||
GEN9TEST_F(CommandEncoderTest, appendsASetMMIO) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeL3State<FamilyType>::encode(cmdContainer, false);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorLRI, commands.end());
|
||||
}
|
||||
|
||||
GEN9TEST_F(CommandEncoderTest, givenNoSLMSetCorrectMMIO) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeL3State<FamilyType>::encode(cmdContainer, false);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorLRI, commands.end());
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
auto expectedData = PreambleHelper<FamilyType>::isL3Configurable(cmdContainer.getDevice()->getHardwareInfo()) ? 0x80000340u : 0x60000321u;
|
||||
EXPECT_EQ(cmd->getRegisterOffset(), 0x7034u);
|
||||
EXPECT_EQ(cmd->getDataDword(), expectedData);
|
||||
}
|
||||
|
||||
GEN9TEST_F(CommandEncoderTest, givenSLMSetCorrectMMIO) {
|
||||
CommandContainer cmdContainer;
|
||||
cmdContainer.initialize(pDevice);
|
||||
EncodeL3State<FamilyType>::encode(cmdContainer, true);
|
||||
|
||||
GenCmdList commands;
|
||||
CmdParse<FamilyType>::parseCommandBuffer(commands, ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0), cmdContainer.getCommandStream()->getUsed());
|
||||
|
||||
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
|
||||
auto itorLRI = find<MI_LOAD_REGISTER_IMM *>(commands.begin(), commands.end());
|
||||
ASSERT_NE(itorLRI, commands.end());
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itorLRI);
|
||||
EXPECT_EQ(cmd->getRegisterOffset(), 0x7034u);
|
||||
EXPECT_EQ(cmd->getDataDword(), 0x60000321u);
|
||||
}
|
||||
@@ -1,534 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/command_stream/preemption.h"
|
||||
#include "shared/source/helpers/hw_helper.h"
|
||||
#include "fixtures/preemption_fixture.h"
|
||||
#include "opencl/source/built_ins/built_ins.h"
|
||||
#include "opencl/test/unit_test/command_queue/enqueue_fixture.h"
|
||||
#include "opencl/test/unit_test/helpers/hw_parse.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_buffer.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_command_queue.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_csr.h"
|
||||
#include "opencl/test/unit_test/mocks/mock_submissions_aggregator.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
template <>
|
||||
void HardwareParse::findCsrBaseAddress<SKLFamily>() {
|
||||
typedef typename GEN9::GPGPU_CSR_BASE_ADDRESS GPGPU_CSR_BASE_ADDRESS;
|
||||
itorGpgpuCsrBaseAddress = find<GPGPU_CSR_BASE_ADDRESS *>(cmdList.begin(), itorWalker);
|
||||
if (itorGpgpuCsrBaseAddress != itorWalker) {
|
||||
cmdGpgpuCsrBaseAddress = *itorGpgpuCsrBaseAddress;
|
||||
}
|
||||
}
|
||||
} // namespace NEO
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using Gen9PreemptionTests = DevicePreemptionTests;
|
||||
using Gen9PreemptionEnqueueKernelTest = PreemptionEnqueueKernelTest;
|
||||
using Gen9MidThreadPreemptionEnqueueKernelTest = MidThreadPreemptionEnqueueKernelTest;
|
||||
using Gen9ThreadGroupPreemptionEnqueueKernelTest = ThreadGroupPreemptionEnqueueKernelTest;
|
||||
|
||||
template <>
|
||||
PreemptionTestHwDetails GetPreemptionTestHwDetails<SKLFamily>() {
|
||||
PreemptionTestHwDetails ret;
|
||||
ret.modeToRegValueMap[PreemptionMode::ThreadGroup] = DwordBuilder::build(1, true) | DwordBuilder::build(2, true, false);
|
||||
ret.modeToRegValueMap[PreemptionMode::MidBatch] = DwordBuilder::build(2, true) | DwordBuilder::build(1, true, false);
|
||||
ret.modeToRegValueMap[PreemptionMode::MidThread] = DwordBuilder::build(2, true, false) | DwordBuilder::build(1, true, false);
|
||||
ret.defaultRegValue = ret.modeToRegValueMap[PreemptionMode::MidBatch];
|
||||
ret.regAddress = 0x2580u;
|
||||
return ret;
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, whenMidThreadPreemptionIsNotAvailableThenDoesNotProgramPreamble) {
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
|
||||
size_t requiredSize = PreemptionHelper::getRequiredStateSipCmdSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(0U, requiredSize);
|
||||
|
||||
LinearStream cmdStream{nullptr, 0};
|
||||
PreemptionHelper::programStateSip<FamilyType>(cmdStream, device->getDevice());
|
||||
EXPECT_EQ(0U, cmdStream.getUsed());
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, whenMidThreadPreemptionIsAvailableThenStateSipIsProgrammed) {
|
||||
using STATE_SIP = typename FamilyType::STATE_SIP;
|
||||
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
executionEnvironment->DisableMidThreadPreemption = 0;
|
||||
|
||||
size_t minCsrSize = device->getHardwareInfo().gtSystemInfo.CsrSizeInMb * MemoryConstants::megaByte;
|
||||
uint64_t minCsrAlignment = 2 * 256 * MemoryConstants::kiloByte;
|
||||
MockGraphicsAllocation csrSurface((void *)minCsrAlignment, minCsrSize);
|
||||
|
||||
size_t requiredCmdStreamSize = PreemptionHelper::getRequiredStateSipCmdSize<FamilyType>(device->getDevice());
|
||||
size_t expectedPreambleSize = sizeof(STATE_SIP);
|
||||
EXPECT_EQ(expectedPreambleSize, requiredCmdStreamSize);
|
||||
|
||||
StackVec<char, 8192> streamStorage(requiredCmdStreamSize);
|
||||
ASSERT_LE(requiredCmdStreamSize, streamStorage.size());
|
||||
|
||||
LinearStream cmdStream{streamStorage.begin(), streamStorage.size()};
|
||||
PreemptionHelper::programStateSip<FamilyType>(cmdStream, device->getDevice());
|
||||
|
||||
HardwareParse hwParsePreamble;
|
||||
hwParsePreamble.parseCommands<FamilyType>(cmdStream);
|
||||
|
||||
auto stateSipCmd = hwParsePreamble.getCommand<STATE_SIP>();
|
||||
ASSERT_NE(nullptr, stateSipCmd);
|
||||
EXPECT_EQ(device->getExecutionEnvironment()->getBuiltIns()->getSipKernel(SipKernelType::Csr, device->getDevice()).getSipAllocation()->getGpuAddressToPatch(), stateSipCmd->getSystemInstructionPointer());
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9ThreadGroupPreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogramThreadGroupNoWa) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
|
||||
pDevice->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
|
||||
csr.getMemoryManager()->setForce32BitAllocations(false);
|
||||
csr.setMediaVFEStateDirty(false);
|
||||
auto csrSurface = csr.getPreemptionAllocation();
|
||||
EXPECT_EQ(nullptr, csrSurface);
|
||||
size_t off[3] = {0, 0, 0};
|
||||
size_t gws[3] = {1, 1, 1};
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
|
||||
HardwareParse hwParserCsr;
|
||||
HardwareParse hwParserCmdQ;
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwParserCsr.parseCommands<FamilyType>(csr.commandStream);
|
||||
hwParserCmdQ.parseCommands<FamilyType>(pCmdQ->getCS(1024));
|
||||
auto offsetCsr = csr.commandStream.getUsed();
|
||||
auto offsetCmdQ = pCmdQ->getCS(1024).getUsed();
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
pCmdQ->flush();
|
||||
hwParserCsr.parseCommands<FamilyType>(csr.commandStream, offsetCsr);
|
||||
hwParserCmdQ.parseCommands<FamilyType>(pCmdQ->getCS(1024), offsetCmdQ);
|
||||
|
||||
EXPECT_EQ(1U, countMmio<FamilyType>(hwParserCsr.cmdList.begin(), hwParserCsr.cmdList.end(), 0x2580u));
|
||||
EXPECT_EQ(0U, countMmio<FamilyType>(hwParserCsr.cmdList.begin(), hwParserCsr.cmdList.end(), 0x2600u));
|
||||
EXPECT_EQ(0U, countMmio<FamilyType>(hwParserCmdQ.cmdList.begin(), hwParserCmdQ.cmdList.end(), 0x2580u));
|
||||
EXPECT_EQ(0U, countMmio<FamilyType>(hwParserCmdQ.cmdList.begin(), hwParserCmdQ.cmdList.end(), 0x2600u));
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9ThreadGroupPreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogramThreadGroupWa) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
|
||||
pDevice->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
|
||||
csr.getMemoryManager()->setForce32BitAllocations(false);
|
||||
csr.setMediaVFEStateDirty(false);
|
||||
auto csrSurface = csr.getPreemptionAllocation();
|
||||
EXPECT_EQ(nullptr, csrSurface);
|
||||
HardwareParse hwCsrParser;
|
||||
HardwareParse hwCmdQParser;
|
||||
size_t off[3] = {0, 0, 0};
|
||||
size_t gws[3] = {1, 1, 1};
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwCsrParser.parseCommands<FamilyType>(csr.commandStream);
|
||||
hwCsrParser.findHardwareCommands<FamilyType>();
|
||||
hwCmdQParser.parseCommands<FamilyType>(pCmdQ->getCS(1024));
|
||||
hwCmdQParser.findHardwareCommands<FamilyType>();
|
||||
auto offsetCsr = csr.commandStream.getUsed();
|
||||
auto offsetCmdQ = pCmdQ->getCS(1024).getUsed();
|
||||
|
||||
bool foundOne = false;
|
||||
for (auto it : hwCsrParser.lriList) {
|
||||
auto cmd = genCmdCast<typename FamilyType::MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmd->getRegisterOffset() == 0x2580u) {
|
||||
EXPECT_FALSE(foundOne);
|
||||
foundOne = true;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(foundOne);
|
||||
hwCsrParser.cmdList.clear();
|
||||
hwCsrParser.lriList.clear();
|
||||
|
||||
int foundWaLri = 0;
|
||||
int foundWaLriBegin = 0;
|
||||
int foundWaLriEnd = 0;
|
||||
for (auto it : hwCmdQParser.lriList) {
|
||||
auto cmd = genCmdCast<typename FamilyType::MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmd->getRegisterOffset() == 0x2600u) {
|
||||
foundWaLri++;
|
||||
if (cmd->getDataDword() == 0xFFFFFFFF) {
|
||||
foundWaLriBegin++;
|
||||
}
|
||||
if (cmd->getDataDword() == 0x0) {
|
||||
foundWaLriEnd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(2, foundWaLri);
|
||||
EXPECT_EQ(1, foundWaLriBegin);
|
||||
EXPECT_EQ(1, foundWaLriEnd);
|
||||
hwCmdQParser.cmdList.clear();
|
||||
hwCmdQParser.lriList.clear();
|
||||
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwCsrParser.parseCommands<FamilyType>(csr.commandStream, offsetCsr);
|
||||
hwCsrParser.findHardwareCommands<FamilyType>();
|
||||
|
||||
hwCmdQParser.parseCommands<FamilyType>(pCmdQ->getCS(1024), offsetCmdQ);
|
||||
hwCmdQParser.findHardwareCommands<FamilyType>();
|
||||
|
||||
for (auto it : hwCsrParser.lriList) {
|
||||
auto cmd = genCmdCast<typename FamilyType::MI_LOAD_REGISTER_IMM *>(it);
|
||||
EXPECT_FALSE(cmd->getRegisterOffset() == 0x2580u);
|
||||
}
|
||||
|
||||
foundWaLri = 0;
|
||||
foundWaLriBegin = 0;
|
||||
foundWaLriEnd = 0;
|
||||
for (auto it : hwCmdQParser.lriList) {
|
||||
auto cmd = genCmdCast<typename FamilyType::MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmd->getRegisterOffset() == 0x2600u) {
|
||||
foundWaLri++;
|
||||
if (cmd->getDataDword() == 0xFFFFFFFF) {
|
||||
foundWaLriBegin++;
|
||||
}
|
||||
if (cmd->getDataDword() == 0x0) {
|
||||
foundWaLriEnd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(2, foundWaLri);
|
||||
EXPECT_EQ(1, foundWaLriBegin);
|
||||
EXPECT_EQ(1, foundWaLriEnd);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionEnqueueKernelTest, givenValidKernelForPreemptionWhenEnqueueKernelCalledThenPassDevicePreemptionModeThreadGroup) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
|
||||
auto mockCsr = new MockCsrHw2<FamilyType>(*pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
pDevice->resetCommandStreamReceiver(mockCsr);
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
MultiDispatchInfo multiDispatch(mockKernel.mockKernel);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, PreemptionHelper::taskPreemptionMode(*pDevice, multiDispatch));
|
||||
|
||||
size_t gws[3] = {1, 0, 0};
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, nullptr, gws, nullptr, 0, nullptr, nullptr);
|
||||
pCmdQ->flush();
|
||||
|
||||
EXPECT_EQ(1, mockCsr->flushCalledCount);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, mockCsr->passedDispatchFlags.preemptionMode);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionEnqueueKernelTest, givenValidKernelForPreemptionWhenEnqueueKernelCalledAndBlockedThenPassDevicePreemptionModeThreadGroup) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
|
||||
auto mockCsr = new MockCsrHw2<FamilyType>(*pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
pDevice->resetCommandStreamReceiver(mockCsr);
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
MultiDispatchInfo multiDispatch(mockKernel.mockKernel);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, PreemptionHelper::taskPreemptionMode(*pDevice, multiDispatch));
|
||||
|
||||
UserEvent userEventObj;
|
||||
cl_event userEvent = &userEventObj;
|
||||
size_t gws[3] = {1, 0, 0};
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, nullptr, gws, nullptr, 1, &userEvent, nullptr);
|
||||
pCmdQ->flush();
|
||||
EXPECT_EQ(0, mockCsr->flushCalledCount);
|
||||
|
||||
userEventObj.setStatus(CL_COMPLETE);
|
||||
pCmdQ->flush();
|
||||
EXPECT_EQ(1, mockCsr->flushCalledCount);
|
||||
EXPECT_EQ(PreemptionMode::ThreadGroup, mockCsr->passedDispatchFlags.preemptionMode);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9MidThreadPreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogramMidThreadNoWa) {
|
||||
typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
typedef typename FamilyType::GPGPU_CSR_BASE_ADDRESS GPGPU_CSR_BASE_ADDRESS;
|
||||
|
||||
pDevice->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
|
||||
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
|
||||
csr.getMemoryManager()->setForce32BitAllocations(false);
|
||||
csr.setMediaVFEStateDirty(false);
|
||||
auto csrSurface = csr.getPreemptionAllocation();
|
||||
ASSERT_NE(nullptr, csrSurface);
|
||||
HardwareParse hwCsrParser;
|
||||
HardwareParse hwCmdQParser;
|
||||
size_t off[3] = {0, 0, 0};
|
||||
size_t gws[3] = {1, 1, 1};
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwCsrParser.parseCommands<FamilyType>(csr.commandStream);
|
||||
hwCsrParser.findHardwareCommands<FamilyType>();
|
||||
hwCmdQParser.parseCommands<FamilyType>(pCmdQ->getCS(1024));
|
||||
hwCmdQParser.findHardwareCommands<FamilyType>();
|
||||
auto offsetCsr = csr.commandStream.getUsed();
|
||||
auto offsetCmdQ = pCmdQ->getCS(1024).getUsed();
|
||||
|
||||
bool foundOneLri = false;
|
||||
for (auto it : hwCsrParser.lriList) {
|
||||
auto cmdLri = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmdLri->getRegisterOffset() == 0x2580u) {
|
||||
EXPECT_FALSE(foundOneLri);
|
||||
foundOneLri = true;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(foundOneLri);
|
||||
|
||||
bool foundWaLri = false;
|
||||
for (auto it : hwCmdQParser.lriList) {
|
||||
auto cmdLri = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmdLri->getRegisterOffset() == 0x2600u) {
|
||||
foundWaLri = true;
|
||||
}
|
||||
}
|
||||
EXPECT_FALSE(foundWaLri);
|
||||
|
||||
hwCsrParser.findCsrBaseAddress<FamilyType>();
|
||||
ASSERT_NE(nullptr, hwCsrParser.cmdGpgpuCsrBaseAddress);
|
||||
auto cmdCsr = genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(hwCsrParser.cmdGpgpuCsrBaseAddress);
|
||||
ASSERT_NE(nullptr, cmdCsr);
|
||||
EXPECT_EQ(csrSurface->getGpuAddressToPatch(), cmdCsr->getGpgpuCsrBaseAddress());
|
||||
|
||||
hwCsrParser.cmdList.clear();
|
||||
hwCsrParser.lriList.clear();
|
||||
hwCsrParser.cmdGpgpuCsrBaseAddress = nullptr;
|
||||
hwCmdQParser.cmdList.clear();
|
||||
hwCmdQParser.lriList.clear();
|
||||
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwCsrParser.parseCommands<FamilyType>(csr.commandStream, offsetCsr);
|
||||
hwCsrParser.findHardwareCommands<FamilyType>();
|
||||
hwCmdQParser.parseCommands<FamilyType>(csr.commandStream, offsetCmdQ);
|
||||
hwCmdQParser.findHardwareCommands<FamilyType>();
|
||||
|
||||
for (auto it : hwCsrParser.lriList) {
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
EXPECT_FALSE(cmd->getRegisterOffset() == 0x2580u);
|
||||
}
|
||||
|
||||
hwCsrParser.findCsrBaseAddress<FamilyType>();
|
||||
EXPECT_EQ(nullptr, hwCsrParser.cmdGpgpuCsrBaseAddress);
|
||||
|
||||
for (auto it : hwCmdQParser.lriList) {
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
EXPECT_FALSE(cmd->getRegisterOffset() == 0x2600u);
|
||||
}
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9MidThreadPreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogramMidThreadWa) {
|
||||
typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
typedef typename FamilyType::GPGPU_CSR_BASE_ADDRESS GPGPU_CSR_BASE_ADDRESS;
|
||||
|
||||
pDevice->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
|
||||
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
|
||||
csr.getMemoryManager()->setForce32BitAllocations(false);
|
||||
csr.setMediaVFEStateDirty(false);
|
||||
auto csrSurface = csr.getPreemptionAllocation();
|
||||
ASSERT_NE(nullptr, csrSurface);
|
||||
HardwareParse hwCsrParser;
|
||||
HardwareParse hwCmdQParser;
|
||||
size_t off[3] = {0, 0, 0};
|
||||
size_t gws[3] = {1, 1, 1};
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwCsrParser.parseCommands<FamilyType>(csr.commandStream);
|
||||
hwCsrParser.findHardwareCommands<FamilyType>();
|
||||
hwCmdQParser.parseCommands<FamilyType>(pCmdQ->getCS(1024));
|
||||
hwCmdQParser.findHardwareCommands<FamilyType>();
|
||||
auto offsetCsr = csr.commandStream.getUsed();
|
||||
auto offsetCmdQ = pCmdQ->getCS(1024).getUsed();
|
||||
|
||||
bool foundOneLri = false;
|
||||
for (auto it : hwCsrParser.lriList) {
|
||||
auto cmdLri = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmdLri->getRegisterOffset() == 0x2580u) {
|
||||
EXPECT_FALSE(foundOneLri);
|
||||
foundOneLri = true;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(foundOneLri);
|
||||
|
||||
int foundWaLri = 0;
|
||||
int foundWaLriBegin = 0;
|
||||
int foundWaLriEnd = 0;
|
||||
for (auto it : hwCmdQParser.lriList) {
|
||||
auto cmdLri = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmdLri->getRegisterOffset() == 0x2600u) {
|
||||
foundWaLri++;
|
||||
if (cmdLri->getDataDword() == 0xFFFFFFFF) {
|
||||
foundWaLriBegin++;
|
||||
}
|
||||
if (cmdLri->getDataDword() == 0x0) {
|
||||
foundWaLriEnd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(2, foundWaLri);
|
||||
EXPECT_EQ(1, foundWaLriBegin);
|
||||
EXPECT_EQ(1, foundWaLriEnd);
|
||||
|
||||
hwCsrParser.findCsrBaseAddress<FamilyType>();
|
||||
ASSERT_NE(nullptr, hwCsrParser.cmdGpgpuCsrBaseAddress);
|
||||
auto cmdCsr = genCmdCast<GPGPU_CSR_BASE_ADDRESS *>(hwCsrParser.cmdGpgpuCsrBaseAddress);
|
||||
ASSERT_NE(nullptr, cmdCsr);
|
||||
EXPECT_EQ(csrSurface->getGpuAddressToPatch(), cmdCsr->getGpgpuCsrBaseAddress());
|
||||
|
||||
hwCsrParser.cmdList.clear();
|
||||
hwCsrParser.lriList.clear();
|
||||
hwCsrParser.cmdGpgpuCsrBaseAddress = nullptr;
|
||||
hwCmdQParser.cmdList.clear();
|
||||
hwCmdQParser.lriList.clear();
|
||||
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
|
||||
hwCsrParser.parseCommands<FamilyType>(csr.commandStream, offsetCsr);
|
||||
hwCsrParser.findHardwareCommands<FamilyType>();
|
||||
hwCmdQParser.parseCommands<FamilyType>(pCmdQ->getCS(1024), offsetCmdQ);
|
||||
hwCmdQParser.findHardwareCommands<FamilyType>();
|
||||
|
||||
for (auto it : hwCsrParser.lriList) {
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
EXPECT_FALSE(cmd->getRegisterOffset() == 0x2580u);
|
||||
}
|
||||
|
||||
hwCsrParser.findCsrBaseAddress<FamilyType>();
|
||||
EXPECT_EQ(nullptr, hwCsrParser.cmdGpgpuCsrBaseAddress);
|
||||
|
||||
foundWaLri = 0;
|
||||
foundWaLriBegin = 0;
|
||||
foundWaLriEnd = 0;
|
||||
for (auto it : hwCmdQParser.lriList) {
|
||||
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(it);
|
||||
if (cmd->getRegisterOffset() == 0x2600u) {
|
||||
foundWaLri++;
|
||||
if (cmd->getDataDword() == 0xFFFFFFFF) {
|
||||
foundWaLriBegin++;
|
||||
}
|
||||
if (cmd->getDataDword() == 0x0) {
|
||||
foundWaLriEnd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(2, foundWaLri);
|
||||
EXPECT_EQ(1, foundWaLriBegin);
|
||||
EXPECT_EQ(1, foundWaLriEnd);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionEnqueueKernelTest, givenDisabledPreemptionWhenEnqueueKernelCalledThenPassDisabledPreemptionMode) {
|
||||
pDevice->setPreemptionMode(PreemptionMode::Disabled);
|
||||
|
||||
auto mockCsr = new MockCsrHw2<FamilyType>(*pDevice->executionEnvironment, pDevice->getRootDeviceIndex());
|
||||
pDevice->resetCommandStreamReceiver(mockCsr);
|
||||
|
||||
MockKernelWithInternals mockKernel(*pClDevice);
|
||||
MultiDispatchInfo multiDispatch(mockKernel.mockKernel);
|
||||
EXPECT_EQ(PreemptionMode::Disabled, PreemptionHelper::taskPreemptionMode(*pDevice, multiDispatch));
|
||||
|
||||
size_t gws[3] = {1, 0, 0};
|
||||
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, nullptr, gws, nullptr, 0, nullptr, nullptr);
|
||||
pCmdQ->flush();
|
||||
|
||||
EXPECT_EQ(1, mockCsr->flushCalledCount);
|
||||
EXPECT_EQ(PreemptionMode::Disabled, mockCsr->passedDispatchFlags.preemptionMode);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, getPreemptionWaCsSizeMidBatch) {
|
||||
size_t expectedSize = 0;
|
||||
device->setPreemptionMode(PreemptionMode::MidBatch);
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, getPreemptionWaCsSizeThreadGroupNoWa) {
|
||||
size_t expectedSize = 0;
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, getPreemptionWaCsSizeThreadGroupWa) {
|
||||
typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
size_t expectedSize = 2 * sizeof(MI_LOAD_REGISTER_IMM);
|
||||
device->setPreemptionMode(PreemptionMode::ThreadGroup);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, getPreemptionWaCsSizeMidThreadNoWa) {
|
||||
size_t expectedSize = 0;
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = false;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, getPreemptionWaCsSizeMidThreadWa) {
|
||||
typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
|
||||
size_t expectedSize = 2 * sizeof(MI_LOAD_REGISTER_IMM);
|
||||
device->setPreemptionMode(PreemptionMode::MidThread);
|
||||
device->getExecutionEnvironment()->getMutableHardwareInfo()->workaroundTable.waModifyVFEStateAfterGPGPUPreemption = true;
|
||||
size_t size = PreemptionHelper::getPreemptionWaCsSize<FamilyType>(device->getDevice());
|
||||
EXPECT_EQ(expectedSize, size);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, givenInterfaceDescriptorDataWhenAnyPreemptionModeThenNoChange) {
|
||||
using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA;
|
||||
|
||||
INTERFACE_DESCRIPTOR_DATA idd;
|
||||
INTERFACE_DESCRIPTOR_DATA iddArg;
|
||||
int ret;
|
||||
|
||||
idd = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
iddArg = FamilyType::cmdInitInterfaceDescriptorData;
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::Disabled);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidBatch);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::ThreadGroup);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
PreemptionHelper::programInterfaceDescriptorDataPreemption<FamilyType>(&iddArg, PreemptionMode::MidThread);
|
||||
ret = memcmp(&idd, &iddArg, sizeof(INTERFACE_DESCRIPTOR_DATA));
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
GEN9TEST_F(Gen9PreemptionTests, givenMidThreadPreemptionModeWhenStateSipIsProgrammedThenSipEqualsSipAllocationGpuAddressToPatch) {
|
||||
using STATE_SIP = typename FamilyType::STATE_SIP;
|
||||
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
|
||||
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
|
||||
auto cmdSizePreemptionMidThread = PreemptionHelper::getRequiredStateSipCmdSize<FamilyType>(*mockDevice);
|
||||
|
||||
StackVec<char, 4096> preemptionBuffer;
|
||||
preemptionBuffer.resize(cmdSizePreemptionMidThread);
|
||||
LinearStream preemptionStream(&*preemptionBuffer.begin(), preemptionBuffer.size());
|
||||
|
||||
PreemptionHelper::programStateSip<FamilyType>(preemptionStream, *mockDevice);
|
||||
|
||||
HardwareParse hwParserOnlyPreemption;
|
||||
hwParserOnlyPreemption.parseCommands<FamilyType>(preemptionStream, 0);
|
||||
auto cmd = hwParserOnlyPreemption.getCommand<STATE_SIP>();
|
||||
EXPECT_NE(nullptr, cmd);
|
||||
|
||||
auto sipType = SipKernel::getSipKernelType(mockDevice->getHardwareInfo().platform.eRenderCoreFamily, mockDevice->isDebuggerActive());
|
||||
EXPECT_EQ(mockDevice->getExecutionEnvironment()->getBuiltIns()->getSipKernel(sipType, *mockDevice).getSipAllocation()->getGpuAddressToPatch(), cmd->getSystemInstructionPointer());
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_HELPERS_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debug_manager_state_restore.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/default_hw_info.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/default_hw_info.inl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file_io_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hash_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_helpers_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/memory_leak_listener.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/memory_management.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/simd_helper_tests.inl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/string_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/string_to_hash_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ult_hw_config.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ult_hw_config.inl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ult_hw_helper.h
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_HELPERS_TESTS ${NEO_CORE_HELPERS_TESTS})
|
||||
add_subdirectories()
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/aligned_memory.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
TEST(AlignedFree, nullptrShouldntCrash) {
|
||||
alignedFree(nullptr);
|
||||
}
|
||||
void *ptrAlignedToPage = (void *)0x1000;
|
||||
void *ptrNotAlignedToPage = (void *)0x1001;
|
||||
|
||||
struct AlignedMalloc : public ::testing::TestWithParam<size_t> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
ptr = nullptr;
|
||||
alignAlloc = GetParam();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
alignedFree(ptr);
|
||||
}
|
||||
|
||||
void *ptr;
|
||||
size_t alignAlloc;
|
||||
};
|
||||
|
||||
TEST_P(AlignedMalloc, size0) {
|
||||
size_t sizeAlloc = 0;
|
||||
ptr = alignedMalloc(sizeAlloc, alignAlloc);
|
||||
EXPECT_NE(nullptr, ptr);
|
||||
EXPECT_EQ(0u, (uintptr_t)ptr % alignAlloc);
|
||||
}
|
||||
|
||||
TEST_P(AlignedMalloc, size4096) {
|
||||
size_t sizeAlloc = 4096;
|
||||
ptr = alignedMalloc(sizeAlloc, alignAlloc);
|
||||
EXPECT_NE(nullptr, ptr);
|
||||
EXPECT_EQ(0u, (uintptr_t)ptr % alignAlloc);
|
||||
}
|
||||
|
||||
TEST(AlignedMallocTests, size0align4096) {
|
||||
size_t sizeAlloc = 0;
|
||||
auto ptr = alignedMalloc(sizeAlloc, 4096);
|
||||
EXPECT_NE(nullptr, ptr);
|
||||
EXPECT_EQ(0u, (uintptr_t)ptr % 4096);
|
||||
alignedFree(ptr);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
AlignedMallocParameterized,
|
||||
AlignedMalloc,
|
||||
testing::Values(
|
||||
1,
|
||||
4,
|
||||
8,
|
||||
64,
|
||||
4096));
|
||||
|
||||
struct AlignUp : public ::testing::TestWithParam<size_t> {
|
||||
};
|
||||
|
||||
TEST_P(AlignUp, belowAlignmentBefore) {
|
||||
uintptr_t addrBefore = 0x1fffffff;
|
||||
auto ptrBefore = (uint32_t *)addrBefore;
|
||||
|
||||
auto alignment = GetParam();
|
||||
auto ptrAfter = alignUp(ptrBefore, alignment);
|
||||
auto addrAfter = (uintptr_t)ptrAfter;
|
||||
|
||||
EXPECT_EQ(0u, addrAfter % alignment);
|
||||
}
|
||||
|
||||
TEST_P(AlignUp, AtAlignmentBefore) {
|
||||
uintptr_t addrBefore = 0x20000000;
|
||||
auto ptrBefore = (uint32_t *)addrBefore;
|
||||
|
||||
auto alignment = GetParam();
|
||||
auto ptrAfter = alignUp(ptrBefore, alignment);
|
||||
auto addrAfter = (uintptr_t)ptrAfter;
|
||||
|
||||
EXPECT_EQ(0u, addrAfter % alignment);
|
||||
}
|
||||
|
||||
TEST_P(AlignUp, AboveAlignmentBefore) {
|
||||
uintptr_t addrBefore = 0x20000001;
|
||||
auto ptrBefore = (uint32_t *)addrBefore;
|
||||
|
||||
auto alignment = GetParam();
|
||||
auto ptrAfter = alignUp(ptrBefore, alignment);
|
||||
auto addrAfter = (uintptr_t)ptrAfter;
|
||||
|
||||
EXPECT_EQ(0u, addrAfter % alignment);
|
||||
}
|
||||
|
||||
TEST_P(AlignUp, preserve64Bit) {
|
||||
uint64_t aligned = 1ULL << 48;
|
||||
auto alignment = GetParam();
|
||||
auto result = alignUp(aligned, alignment);
|
||||
EXPECT_EQ(aligned, result);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
AlignUpParameterized,
|
||||
AlignUp,
|
||||
testing::Values(
|
||||
1,
|
||||
4,
|
||||
8,
|
||||
32,
|
||||
64,
|
||||
256,
|
||||
4096));
|
||||
|
||||
TEST(AlignWholeSize, alignWholeSizeToPage) {
|
||||
int size = 1;
|
||||
auto retSize = alignSizeWholePage(ptrAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u);
|
||||
}
|
||||
TEST(AlignWholeSize, sizeGreaterThenPageResultsIn2Pages) {
|
||||
|
||||
int size = 4097;
|
||||
auto retSize = alignSizeWholePage(ptrAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u * 2);
|
||||
}
|
||||
TEST(AlignWholeSize, allocationNotPageAligned) {
|
||||
|
||||
int size = 4097;
|
||||
auto retSize = alignSizeWholePage(ptrNotAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u * 2);
|
||||
}
|
||||
TEST(AlignWholeSize, ptrNotAligned) {
|
||||
|
||||
int size = 1;
|
||||
auto retSize = alignSizeWholePage(ptrNotAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u);
|
||||
}
|
||||
TEST(AlignWholeSize, allocationFitsToOnePage) {
|
||||
|
||||
int size = 4095;
|
||||
auto retSize = alignSizeWholePage(ptrNotAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u);
|
||||
}
|
||||
TEST(AlignWholeSize, allocationFitsTo2Pages) {
|
||||
|
||||
int size = 4095 + 4096;
|
||||
auto retSize = alignSizeWholePage(ptrNotAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u * 2);
|
||||
}
|
||||
TEST(AlignWholeSize, allocationOverlapsToAnotherPage) {
|
||||
|
||||
int size = 4096;
|
||||
auto retSize = alignSizeWholePage(ptrNotAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u * 2);
|
||||
}
|
||||
TEST(AlignWholeSize, allocationOverlapsTo2AnotherPage) {
|
||||
|
||||
int size = 4096 * 2;
|
||||
auto retSize = alignSizeWholePage(ptrNotAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u * 3);
|
||||
}
|
||||
TEST(AlignWholeSize, ptrProperlyAlignedTo2Pages) {
|
||||
|
||||
int size = 4096 * 2;
|
||||
auto retSize = alignSizeWholePage(ptrAlignedToPage, size);
|
||||
EXPECT_EQ(retSize, 4096u * 2);
|
||||
}
|
||||
|
||||
TEST(AlignDown, ptrAlignedToPageWhenAlignedDownReturnsTheSamePointer) {
|
||||
void *ptr = (void *)0x1000;
|
||||
|
||||
auto alignedDownPtr = alignDown(ptr, MemoryConstants::pageSize);
|
||||
EXPECT_EQ(ptr, alignedDownPtr);
|
||||
}
|
||||
TEST(AlignDown, ptrNotAlignedToPageWhenAlignedDownReturnsPageAlignedPointer) {
|
||||
void *ptr = (void *)0x1001;
|
||||
void *expected_ptr = (void *)0x1000;
|
||||
auto alignedDownPtr = alignDown(ptr, MemoryConstants::pageSize);
|
||||
EXPECT_EQ(expected_ptr, alignedDownPtr);
|
||||
}
|
||||
|
||||
TEST(AlignDown, ptrNotAlignedToPage2WhenAlignedDownReturnsPageAlignedPointer) {
|
||||
void *ptr = (void *)0x1241;
|
||||
void *expected_ptr = (void *)0x1000;
|
||||
auto alignedDownPtr = alignDown(ptr, MemoryConstants::pageSize);
|
||||
EXPECT_EQ(expected_ptr, alignedDownPtr);
|
||||
}
|
||||
|
||||
TEST(AlignDown, ptrNotAlignedToPage3WhenAlignedDownReturnsPageAlignedPointer) {
|
||||
void *ptr = (void *)0x3241;
|
||||
void *expected_ptr = (void *)0x3000;
|
||||
auto alignedDownPtr = alignDown(ptr, MemoryConstants::pageSize);
|
||||
EXPECT_EQ(expected_ptr, alignedDownPtr);
|
||||
}
|
||||
|
||||
TEST(AlignDown, ptrNotAlignedToDwordWhenAlignedDownReturnsDwordAlignedPointer) {
|
||||
void *ptr = (void *)0x3241;
|
||||
void *expected_ptr = (void *)0x3240;
|
||||
auto alignedDownPtr = alignDown(ptr, 4);
|
||||
EXPECT_EQ(expected_ptr, alignedDownPtr);
|
||||
}
|
||||
|
||||
TEST(AlignDown, preserve64Bit) {
|
||||
uint64_t aligned = 1ULL << 48;
|
||||
auto result = alignDown(aligned, MemoryConstants::pageSize);
|
||||
EXPECT_EQ(aligned, result);
|
||||
}
|
||||
|
||||
TEST(DLLbitness, Given32or64BitLibraryWhenAskedIfItIs32BitThenProperValueIsReturned) {
|
||||
auto pointerSize = sizeof(void *);
|
||||
if (pointerSize == 8) {
|
||||
EXPECT_FALSE(is32bit);
|
||||
EXPECT_TRUE(is64bit);
|
||||
} else if (pointerSize == 4) {
|
||||
EXPECT_TRUE(is32bit);
|
||||
EXPECT_FALSE(is64bit);
|
||||
} else {
|
||||
FAIL() << "unrecognized bitness";
|
||||
}
|
||||
auto pointerSizeFromSizeT = sizeof(size_t);
|
||||
if (pointerSizeFromSizeT == 8) {
|
||||
EXPECT_FALSE(is32bit);
|
||||
EXPECT_TRUE(is64bit);
|
||||
} else if (pointerSizeFromSizeT == 4) {
|
||||
EXPECT_TRUE(is32bit);
|
||||
EXPECT_FALSE(is64bit);
|
||||
} else {
|
||||
FAIL() << "unrecognized bitness";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class IsAlignedTests : public ::testing::Test {
|
||||
};
|
||||
|
||||
typedef ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double> IsAlignedTypes;
|
||||
|
||||
TYPED_TEST_CASE(IsAlignedTests, IsAlignedTypes);
|
||||
TYPED_TEST(IsAlignedTests, aligned) {
|
||||
TypeParam *ptr = reinterpret_cast<TypeParam *>(static_cast<uintptr_t>(0xdeadbeefu));
|
||||
// one byte alignment should always return true
|
||||
if (alignof(TypeParam) == 1)
|
||||
EXPECT_TRUE(isAligned(ptr));
|
||||
else
|
||||
EXPECT_FALSE(isAligned(ptr));
|
||||
|
||||
auto ptr1 = reinterpret_cast<TypeParam *>(reinterpret_cast<uintptr_t>(ptr) & ~(alignof(TypeParam) - 1));
|
||||
EXPECT_TRUE(isAligned(ptr1));
|
||||
|
||||
auto ptr2 = reinterpret_cast<TypeParam *>(reinterpret_cast<uintptr_t>(ptr) & ~((alignof(TypeParam) << 1) - 1));
|
||||
EXPECT_TRUE(isAligned(ptr2));
|
||||
|
||||
// this is hard to align in the middle of byte aligned types
|
||||
if (alignof(TypeParam) == 1)
|
||||
return;
|
||||
|
||||
auto ptr3 = reinterpret_cast<TypeParam *>(reinterpret_cast<uintptr_t>(ptr) & ~((alignof(TypeParam) >> 1) - 1));
|
||||
EXPECT_FALSE(isAligned(ptr3));
|
||||
}
|
||||
|
||||
TEST(IsAligned, nonPointerType) {
|
||||
EXPECT_TRUE(isAligned<3>(0));
|
||||
EXPECT_FALSE(isAligned<3>(1));
|
||||
EXPECT_FALSE(isAligned<3>(2));
|
||||
EXPECT_TRUE(isAligned<3>(3));
|
||||
EXPECT_FALSE(isAligned<3>(4));
|
||||
EXPECT_FALSE(isAligned<3>(5));
|
||||
EXPECT_TRUE(isAligned<3>(6));
|
||||
}
|
||||
|
||||
TEST(IsAligned, supportsConstexprEvaluation) {
|
||||
static_assert(false == isAligned<3>(2), "");
|
||||
static_assert(true == isAligned<3>(3), "");
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "shared/source/debug_settings/debug_settings_manager.h"
|
||||
#include "shared/source/utilities/debug_settings_reader.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class DebugManagerStateRestore {
|
||||
public:
|
||||
DebugManagerStateRestore() {
|
||||
debugVarSnapshot = DebugManager.flags;
|
||||
injectFcnSnapshot = DebugManager.injectFcn;
|
||||
}
|
||||
~DebugManagerStateRestore() {
|
||||
DebugManager.flags = debugVarSnapshot;
|
||||
DebugManager.injectFcn = injectFcnSnapshot;
|
||||
#undef DECLARE_DEBUG_VARIABLE
|
||||
#define DECLARE_DEBUG_VARIABLE(dataType, variableName, defaultValue, description) shrink(DebugManager.flags.variableName.getRef());
|
||||
#include "debug_variables.inl"
|
||||
#undef DECLARE_DEBUG_VARIABLE
|
||||
}
|
||||
DebugVariables debugVarSnapshot;
|
||||
void *injectFcnSnapshot = nullptr;
|
||||
|
||||
protected:
|
||||
void shrink(std::string &flag) {
|
||||
flag.shrink_to_fit();
|
||||
}
|
||||
void shrink(int32_t &flag) {}
|
||||
void shrink(bool &flag) {}
|
||||
};
|
||||
|
||||
class RegistryReaderMock : public SettingsReader {
|
||||
public:
|
||||
RegistryReaderMock() {}
|
||||
~RegistryReaderMock() override {}
|
||||
|
||||
unsigned int forceRetValue = 1;
|
||||
|
||||
int32_t getSetting(const char *settingName, int32_t defaultValue) override {
|
||||
return static_cast<int32_t>(forceRetValue);
|
||||
}
|
||||
bool getSetting(const char *settingName, bool defaultValue) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string getSetting(const char *settingName, const std::string &value) override {
|
||||
return "";
|
||||
}
|
||||
const char *appSpecificLocation(const std::string &name) override {
|
||||
return name.c_str();
|
||||
}
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
|
||||
namespace NEO {
|
||||
struct HardwareInfo;
|
||||
extern const HardwareInfo **platformDevices;
|
||||
|
||||
} // namespace NEO
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/array_count.h"
|
||||
#include "shared/source/helpers/hw_cmds.h"
|
||||
|
||||
namespace NEO {
|
||||
static const HardwareInfo *DefaultPlatformDevices[] = {
|
||||
&DEFAULT_TEST_PLATFORM::hwInfo,
|
||||
};
|
||||
|
||||
const HardwareInfo **platformDevices = DefaultPlatformDevices;
|
||||
} // namespace NEO
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/file_io.h"
|
||||
#include "shared/source/helpers/stdio.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
TEST(FileIO, existsHasSize) {
|
||||
std::string fileName("fileIO.bin");
|
||||
std::remove(fileName.c_str());
|
||||
ASSERT_FALSE(fileExists(fileName.c_str()));
|
||||
|
||||
FILE *fp = nullptr;
|
||||
fopen_s(&fp, fileName.c_str(), "wb");
|
||||
ASSERT_NE(nullptr, fp);
|
||||
fprintf(fp, "TEST");
|
||||
fclose(fp);
|
||||
|
||||
EXPECT_TRUE(fileExists(fileName.c_str()));
|
||||
EXPECT_TRUE(fileExistsHasSize(fileName.c_str()));
|
||||
}
|
||||
|
||||
TEST(FileIO, existsSizeZero) {
|
||||
std::string fileName("fileIO.bin");
|
||||
std::remove(fileName.c_str());
|
||||
ASSERT_FALSE(fileExists(fileName.c_str()));
|
||||
|
||||
FILE *fp = nullptr;
|
||||
fopen_s(&fp, fileName.c_str(), "wb");
|
||||
ASSERT_NE(nullptr, fp);
|
||||
fclose(fp);
|
||||
|
||||
EXPECT_TRUE(fileExists(fileName.c_str()));
|
||||
EXPECT_FALSE(fileExistsHasSize(fileName.c_str()));
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/hash.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
TEST(HashTests, givenSamePointersWhenHashIsCalculatedThenSame32BitValuesAreGenerated) {
|
||||
uintptr_t ptr1UI = 1;
|
||||
uintptr_t ptr2UI = 1;
|
||||
void *ptr1 = reinterpret_cast<void *>(ptr1UI);
|
||||
void *ptr2 = reinterpret_cast<void *>(ptr2UI);
|
||||
|
||||
uint32_t hash1 = hashPtrToU32(ptr1);
|
||||
uint32_t hash2 = hashPtrToU32(ptr2);
|
||||
|
||||
EXPECT_EQ(hash1, hash2);
|
||||
}
|
||||
|
||||
TEST(HashTests, givenDifferentPointersWhenHashIsCalculatedThenUnique32BitValuesAreGenerated) {
|
||||
uintptr_t ptr1UI = 1;
|
||||
uintptr_t ptr2UI = ptr1UI | (ptr1UI << ((sizeof(uintptr_t) / 2) * 8));
|
||||
void *ptr1 = reinterpret_cast<void *>(ptr1UI);
|
||||
void *ptr2 = reinterpret_cast<void *>(ptr2UI);
|
||||
|
||||
uint32_t hash1 = hashPtrToU32(ptr1);
|
||||
uint32_t hash2 = hashPtrToU32(ptr2);
|
||||
|
||||
EXPECT_NE(hash1, hash2);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/basic_math.h"
|
||||
#include "shared/source/helpers/kernel_helpers.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
struct KernelHelperMaxWorkGroupsTests : ::testing::Test {
|
||||
uint32_t simd = 8;
|
||||
uint32_t threadCount = 8 * 1024;
|
||||
uint32_t dssCount = 16;
|
||||
uint32_t availableSlm = 64 * KB;
|
||||
uint32_t usedSlm = 0;
|
||||
uint32_t maxBarrierCount = 32;
|
||||
uint32_t numberOfBarriers = 0;
|
||||
uint32_t workDim = 3;
|
||||
size_t lws[3] = {10, 10, 10};
|
||||
|
||||
uint32_t getMaxWorkGroupCount() {
|
||||
return KernelHelper::getMaxWorkGroupCount(simd, threadCount, dssCount, availableSlm, usedSlm,
|
||||
maxBarrierCount, numberOfBarriers, workDim, lws);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(KernelHelperMaxWorkGroupsTests, GivenNoBarriersOrSlmUsedWhenCalculatingMaxWorkGroupsCountThenResultIsCalculatedWithSimd) {
|
||||
auto workGroupSize = lws[0] * lws[1] * lws[2];
|
||||
auto expected = threadCount / Math::divideAndRoundUp(workGroupSize, simd);
|
||||
EXPECT_EQ(expected, getMaxWorkGroupCount());
|
||||
}
|
||||
|
||||
TEST_F(KernelHelperMaxWorkGroupsTests, GivenBarriersWhenCalculatingMaxWorkGroupsCountThenResultIsCalculatedWithRegardToBarriersCount) {
|
||||
numberOfBarriers = 16;
|
||||
|
||||
auto expected = dssCount * (maxBarrierCount / numberOfBarriers);
|
||||
EXPECT_EQ(expected, getMaxWorkGroupCount());
|
||||
}
|
||||
|
||||
TEST_F(KernelHelperMaxWorkGroupsTests, GivenUsedSlmSizeWhenCalculatingMaxWorkGroupsCountThenResultIsCalculatedWithRegardToUsedSlmSize) {
|
||||
usedSlm = 4 * KB;
|
||||
|
||||
auto expected = availableSlm / usedSlm;
|
||||
EXPECT_EQ(expected, getMaxWorkGroupCount());
|
||||
}
|
||||
|
||||
TEST_F(KernelHelperMaxWorkGroupsTests, GivenVariousValuesWhenCalculatingMaxWorkGroupsCountThenLowestResultIsAlwaysReturned) {
|
||||
usedSlm = 1 * KB;
|
||||
numberOfBarriers = 1;
|
||||
dssCount = 1;
|
||||
|
||||
workDim = 1;
|
||||
lws[0] = simd;
|
||||
threadCount = 1;
|
||||
EXPECT_EQ(1u, getMaxWorkGroupCount());
|
||||
|
||||
threadCount = 1024;
|
||||
EXPECT_NE(1u, getMaxWorkGroupCount());
|
||||
|
||||
numberOfBarriers = 32;
|
||||
EXPECT_EQ(1u, getMaxWorkGroupCount());
|
||||
|
||||
numberOfBarriers = 1;
|
||||
EXPECT_NE(1u, getMaxWorkGroupCount());
|
||||
|
||||
usedSlm = availableSlm;
|
||||
EXPECT_EQ(1u, getMaxWorkGroupCount());
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "memory_leak_listener.h"
|
||||
|
||||
#include "helpers/memory_management.h"
|
||||
|
||||
using ::testing::TestInfo;
|
||||
using namespace NEO;
|
||||
|
||||
void MemoryLeakListener::OnTestStart(const TestInfo &testInfo) {
|
||||
MemoryManagement::logTraces = MemoryManagement::captureCallStacks;
|
||||
if (MemoryManagement::captureCallStacks) {
|
||||
MemoryManagement::detailedAllocationLoggingActive = true;
|
||||
}
|
||||
MemoryManagement::fastLeakDetectionEnabled = true;
|
||||
}
|
||||
|
||||
void MemoryLeakListener::OnTestEnd(const TestInfo &testInfo) {
|
||||
MemoryManagement::fastLeakDetectionEnabled = false;
|
||||
|
||||
if (testInfo.result()->Passed()) {
|
||||
if (MemoryManagement::fastLeaksDetectionMode != MemoryManagement::LeakDetectionMode::STANDARD) {
|
||||
if (MemoryManagement::fastLeaksDetectionMode == MemoryManagement::LeakDetectionMode::EXPECT_TO_LEAK) {
|
||||
EXPECT_GT(MemoryManagement::fastEventsAllocatedCount, MemoryManagement::fastEventsDeallocatedCount);
|
||||
}
|
||||
MemoryManagement::fastLeaksDetectionMode = MemoryManagement::LeakDetectionMode::STANDARD;
|
||||
} else if (MemoryManagement::captureCallStacks && (MemoryManagement::fastEventsAllocatedCount != MemoryManagement::fastEventsDeallocatedCount)) {
|
||||
auto leak = MemoryManagement::enumerateLeak(MemoryManagement::indexAllocation.load(), MemoryManagement::indexDeallocation.load(), true, true);
|
||||
if (leak != MemoryManagement::failingAllocation) {
|
||||
printf("\n %s ", printCallStack(MemoryManagement::eventsAllocated[leak]).c_str());
|
||||
}
|
||||
EXPECT_EQ(MemoryManagement::indexAllocation.load(), MemoryManagement::indexDeallocation.load());
|
||||
} else if (MemoryManagement::fastEventsAllocatedCount != MemoryManagement::fastEventsDeallocatedCount) {
|
||||
auto leak = MemoryManagement::detectLeaks();
|
||||
EXPECT_EQ(leak, (int)MemoryManagement::failingAllocation) << "To locate call stack, change the value of captureCallStacks to true";
|
||||
}
|
||||
}
|
||||
MemoryManagement::fastEventsAllocatedCount = 0;
|
||||
MemoryManagement::fastEventsDeallocatedCount = 0;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
class MemoryLeakListener : public ::testing::EmptyTestEventListener {
|
||||
protected:
|
||||
void OnTestStart(const ::testing::TestInfo &) override;
|
||||
void OnTestEnd(const ::testing::TestInfo &) override;
|
||||
};
|
||||
} // namespace NEO
|
||||
@@ -1,404 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/memory_management.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <new>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <cstdio>
|
||||
#include <dlfcn.h>
|
||||
#include <execinfo.h>
|
||||
#elif defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
|
||||
#include <DbgHelp.h>
|
||||
#endif
|
||||
|
||||
namespace MemoryManagement {
|
||||
size_t failingAllocation = -1;
|
||||
std::atomic<size_t> numAllocations(0);
|
||||
std::atomic<size_t> indexAllocation(0);
|
||||
std::atomic<size_t> indexDeallocation(0);
|
||||
bool logTraces = false;
|
||||
bool fastLeakDetectionEnabled = false;
|
||||
|
||||
AllocationEvent eventsAllocated[maxEvents];
|
||||
AllocationEvent eventsDeallocated[maxEvents];
|
||||
|
||||
void *fastEventsAllocated[maxEvents];
|
||||
void *fastEventsDeallocated[maxEvents];
|
||||
std::atomic<int> fastEventsAllocatedCount(0);
|
||||
std::atomic<int> fastEventsDeallocatedCount(0);
|
||||
std::atomic<int> fastLeaksDetectionMode(LeakDetectionMode::STANDARD);
|
||||
|
||||
size_t breakOnAllocationEvent = -1;
|
||||
size_t breakOnDeallocationEvent = -1;
|
||||
|
||||
bool detailedAllocationLoggingActive = false;
|
||||
|
||||
// limit size of single allocation in ULT
|
||||
const size_t maxAllowedAllocationSize = 128 * 1024 * 1024 + 4096;
|
||||
|
||||
static void onAllocationEvent() {
|
||||
/*
|
||||
//switch to true to turn on dillignet breakpoint setting place
|
||||
bool setBreakPointHereForLeaks = false;
|
||||
if (setBreakPointHereForLeaks) {
|
||||
if (breakOnAllocationEvent == indexAllocation.load()) {
|
||||
//set breakpoint on line below
|
||||
setBreakPointHereForLeaks = false;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
static void onDeallocationEvent(void *) {
|
||||
/*
|
||||
//switch to true to turn on dillignet breakpoint setting place
|
||||
bool setBreakPointHereForLeaks = false;
|
||||
if (setBreakPointHereForLeaks) {
|
||||
if (breakOnDeallocationEvent == indexDeallocation.load()) {
|
||||
//set breakpoint on line below
|
||||
setBreakPointHereForLeaks = false;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void (*deleteCallback)(void *) = onDeallocationEvent;
|
||||
|
||||
template <AllocationEvent::EventType typeValid, AllocationEvent::EventType typeFail>
|
||||
static void *allocate(size_t size) {
|
||||
onAllocationEvent();
|
||||
|
||||
if (size > maxAllowedAllocationSize) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!fastLeakDetectionEnabled) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *p;
|
||||
|
||||
if (detailedAllocationLoggingActive) {
|
||||
|
||||
auto indexAllocation = MemoryManagement::indexAllocation.fetch_add(1);
|
||||
indexAllocation %= maxEvents;
|
||||
|
||||
auto &eventAllocation = eventsAllocated[indexAllocation];
|
||||
eventAllocation.size = size;
|
||||
|
||||
while ((p = malloc(size)) == nullptr) {
|
||||
eventAllocation.address = p;
|
||||
eventAllocation.event = typeFail;
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
eventAllocation.address = p;
|
||||
eventAllocation.event = typeValid;
|
||||
#if defined(__linux__)
|
||||
eventAllocation.frames = logTraces ? backtrace(eventAllocation.callstack, AllocationEvent::CallStackSize) : 0;
|
||||
#elif defined(_WIN32)
|
||||
eventAllocation.frames = logTraces ? CaptureStackBackTrace(0, AllocationEvent::CallStackSize, eventAllocation.callstack, NULL) : 0;
|
||||
#else
|
||||
eventAllocation.frames = 0;
|
||||
#endif
|
||||
eventAllocation.fastLeakDetectionEnabled = fastLeakDetectionEnabled;
|
||||
|
||||
numAllocations++;
|
||||
} else {
|
||||
p = malloc(size);
|
||||
}
|
||||
|
||||
if (fastLeakDetectionEnabled && p && fastLeaksDetectionMode == LeakDetectionMode::STANDARD) {
|
||||
auto currentIndex = fastEventsAllocatedCount++;
|
||||
fastEventsAllocated[currentIndex] = p;
|
||||
assert(currentIndex <= fastEvents);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template <AllocationEvent::EventType typeValid, AllocationEvent::EventType typeFail>
|
||||
static void *allocate(size_t size, const std::nothrow_t &) {
|
||||
onAllocationEvent();
|
||||
|
||||
if (size > maxAllowedAllocationSize) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!fastLeakDetectionEnabled) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *p;
|
||||
|
||||
if (detailedAllocationLoggingActive) {
|
||||
|
||||
auto indexAllocation = MemoryManagement::indexAllocation.fetch_add(1);
|
||||
indexAllocation %= maxEvents;
|
||||
|
||||
p = indexAllocation == failingAllocation
|
||||
? nullptr
|
||||
: malloc(size);
|
||||
|
||||
auto &eventAllocation = eventsAllocated[indexAllocation];
|
||||
eventAllocation.event = p
|
||||
? typeValid
|
||||
: typeFail;
|
||||
eventAllocation.address = p;
|
||||
eventAllocation.size = size;
|
||||
#if defined(__linux__)
|
||||
eventAllocation.frames = logTraces ? backtrace(eventAllocation.callstack, AllocationEvent::CallStackSize) : 0;
|
||||
#elif defined(_WIN32)
|
||||
eventAllocation.frames = logTraces ? CaptureStackBackTrace(0, AllocationEvent::CallStackSize, eventAllocation.callstack, NULL) : 0;
|
||||
#else
|
||||
eventAllocation.frames = 0;
|
||||
#endif
|
||||
eventAllocation.fastLeakDetectionEnabled = fastLeakDetectionEnabled;
|
||||
numAllocations += p ? 1 : 0;
|
||||
} else {
|
||||
p = malloc(size);
|
||||
}
|
||||
|
||||
if (fastLeakDetectionEnabled && p && fastLeaksDetectionMode == LeakDetectionMode::STANDARD) {
|
||||
auto currentIndex = fastEventsAllocatedCount++;
|
||||
fastEventsAllocated[currentIndex] = p;
|
||||
assert(currentIndex <= fastEvents);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template <AllocationEvent::EventType typeValid>
|
||||
static void deallocate(void *p) {
|
||||
deleteCallback(p);
|
||||
|
||||
if (!fastLeakDetectionEnabled) {
|
||||
if (p) {
|
||||
free(p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (p) {
|
||||
if (detailedAllocationLoggingActive) {
|
||||
|
||||
auto indexDeallocation = MemoryManagement::indexDeallocation.fetch_add(1);
|
||||
indexDeallocation %= maxEvents;
|
||||
|
||||
--numAllocations;
|
||||
|
||||
auto &eventDeallocation = eventsDeallocated[indexDeallocation];
|
||||
eventDeallocation.event = typeValid;
|
||||
eventDeallocation.address = p;
|
||||
eventDeallocation.size = -1;
|
||||
#if defined(__linux__)
|
||||
eventDeallocation.frames = logTraces ? backtrace(eventDeallocation.callstack, AllocationEvent::CallStackSize) : 0;
|
||||
#elif defined(_WIN32)
|
||||
eventDeallocation.frames = logTraces ? CaptureStackBackTrace(0, AllocationEvent::CallStackSize, eventDeallocation.callstack, NULL) : 0;
|
||||
#else
|
||||
eventDeallocation.frames = 0;
|
||||
#endif
|
||||
eventDeallocation.fastLeakDetectionEnabled = fastLeakDetectionEnabled;
|
||||
}
|
||||
free(p);
|
||||
|
||||
if (fastLeakDetectionEnabled && p && fastLeaksDetectionMode == LeakDetectionMode::STANDARD) {
|
||||
auto currentIndex = fastEventsDeallocatedCount++;
|
||||
fastEventsDeallocated[currentIndex] = p;
|
||||
assert(currentIndex <= fastEvents);
|
||||
}
|
||||
}
|
||||
}
|
||||
int detectLeaks() {
|
||||
int indexLeak = -1;
|
||||
|
||||
for (int allocationIndex = 0u; allocationIndex < fastEventsAllocatedCount; allocationIndex++) {
|
||||
auto &eventAllocation = fastEventsAllocated[allocationIndex];
|
||||
int deallocationIndex = 0u;
|
||||
for (; deallocationIndex < fastEventsDeallocatedCount; deallocationIndex++) {
|
||||
if (fastEventsDeallocated[deallocationIndex] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (fastEventsDeallocated[deallocationIndex] == eventAllocation) {
|
||||
fastEventsDeallocated[deallocationIndex] = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (deallocationIndex == fastEventsDeallocatedCount) {
|
||||
indexLeak = allocationIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return indexLeak;
|
||||
}
|
||||
|
||||
size_t enumerateLeak(size_t indexAllocationTop, size_t indexDeallocationTop, bool lookFromBack, bool requireCallStack) {
|
||||
using MemoryManagement::AllocationEvent;
|
||||
using MemoryManagement::eventsAllocated;
|
||||
using MemoryManagement::eventsDeallocated;
|
||||
|
||||
static auto start = MemoryManagement::invalidLeakIndex;
|
||||
auto newIndex = start == MemoryManagement::invalidLeakIndex ? 0 : start;
|
||||
bool potentialLeak = false;
|
||||
auto potentialLeakIndex = newIndex;
|
||||
|
||||
for (; newIndex < indexAllocationTop; ++newIndex) {
|
||||
auto currentIndex = lookFromBack ? indexAllocationTop - newIndex - 1 : newIndex;
|
||||
auto &eventAllocation = eventsAllocated[currentIndex];
|
||||
|
||||
if (requireCallStack && eventAllocation.frames == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eventAllocation.event != AllocationEvent::EVENT_UNKNOWN) {
|
||||
// Should be some sort of allocation
|
||||
size_t deleteIndex = 0;
|
||||
for (; deleteIndex < indexDeallocationTop; ++deleteIndex) {
|
||||
auto &eventDeallocation = eventsDeallocated[deleteIndex];
|
||||
|
||||
if (eventDeallocation.address == eventAllocation.address &&
|
||||
eventDeallocation.event != AllocationEvent::EVENT_UNKNOWN) {
|
||||
|
||||
//this memory was once freed, now it is allocated but not freed
|
||||
if (requireCallStack && eventDeallocation.frames == 0) {
|
||||
potentialLeak = true;
|
||||
potentialLeakIndex = currentIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Clear the NEW and DELETE event.
|
||||
eventAllocation.event = AllocationEvent::EVENT_UNKNOWN;
|
||||
eventDeallocation.event = AllocationEvent::EVENT_UNKNOWN;
|
||||
potentialLeak = false;
|
||||
// Found a corresponding match
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (potentialLeak) {
|
||||
return potentialLeakIndex;
|
||||
}
|
||||
|
||||
if (deleteIndex == indexDeallocationTop) {
|
||||
start = newIndex + 1;
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
start = MemoryManagement::invalidLeakIndex;
|
||||
return start;
|
||||
}
|
||||
|
||||
std::string printCallStack(const MemoryManagement::AllocationEvent &event) {
|
||||
std::string result = "";
|
||||
|
||||
printf("printCallStack.%d\n", event.frames);
|
||||
if (!MemoryManagement::captureCallStacks) {
|
||||
printf("for detailed stack information turn on captureCallStacks in memory_management.h\n");
|
||||
}
|
||||
if (event.frames > 0) {
|
||||
#if defined(__linux__)
|
||||
char **bt = backtrace_symbols(event.callstack, event.frames);
|
||||
char *demangled;
|
||||
int status;
|
||||
char output[1024];
|
||||
Dl_info info;
|
||||
result += "\n";
|
||||
for (int i = 0; i < event.frames; ++i) {
|
||||
dladdr(event.callstack[i], &info);
|
||||
if (info.dli_sname) {
|
||||
demangled = nullptr;
|
||||
status = -1;
|
||||
if (info.dli_sname[0] == '_') {
|
||||
demangled = abi::__cxa_demangle(info.dli_sname, nullptr, 0, &status);
|
||||
}
|
||||
snprintf(output, sizeof(output), "%-3d %*p %s + %zd\n",
|
||||
(event.frames - i - 1), (int)(sizeof(void *) + 2), event.callstack[i],
|
||||
status == 0 ? demangled : info.dli_sname == 0 ? bt[i] : info.dli_sname,
|
||||
(char *)event.callstack[i] - (char *)info.dli_saddr);
|
||||
free(demangled);
|
||||
} else {
|
||||
snprintf(output, sizeof(output), "%-3d %*p %s\n",
|
||||
(event.frames - i - 1), (int)(sizeof(void *) + 2), event.callstack[i], bt[i]);
|
||||
}
|
||||
result += std::string(output);
|
||||
}
|
||||
result += "\n";
|
||||
free(bt);
|
||||
#elif defined(_WIN32)
|
||||
SYMBOL_INFO *symbol;
|
||||
HANDLE process;
|
||||
process = GetCurrentProcess();
|
||||
SymInitialize(process, NULL, TRUE);
|
||||
|
||||
symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
|
||||
symbol->MaxNameLen = 255;
|
||||
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
|
||||
for (int i = 0; i < event.frames; i++) {
|
||||
SymFromAddr(process, (DWORD64)(event.callstack[i]), 0, symbol);
|
||||
|
||||
printf("%i: %s - 0x%0" PRIx64 "\n", event.frames - i - 1, symbol->Name, symbol->Address);
|
||||
}
|
||||
|
||||
free(symbol);
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace MemoryManagement
|
||||
|
||||
using MemoryManagement::allocate;
|
||||
using MemoryManagement::AllocationEvent;
|
||||
using MemoryManagement::deallocate;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(disable : 4290)
|
||||
#endif
|
||||
void *operator new(size_t size) {
|
||||
return allocate<AllocationEvent::EVENT_NEW, AllocationEvent::EVENT_NEW_FAIL>(size);
|
||||
}
|
||||
|
||||
void *operator new(size_t size, const std::nothrow_t &) noexcept {
|
||||
return allocate<AllocationEvent::EVENT_NEW_NOTHROW, AllocationEvent::EVENT_NEW_NOTHROW_FAIL>(size, std::nothrow);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size) {
|
||||
return allocate<AllocationEvent::EVENT_NEW_ARRAY, AllocationEvent::EVENT_NEW_ARRAY_FAIL>(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size, const std::nothrow_t &t) noexcept {
|
||||
return allocate<AllocationEvent::EVENT_NEW_ARRAY_NOTHROW, AllocationEvent::EVENT_NEW_ARRAY_NOTHROW_FAIL>(size, std::nothrow);
|
||||
}
|
||||
|
||||
void operator delete(void *p) noexcept {
|
||||
deallocate<AllocationEvent::EVENT_DELETE>(p);
|
||||
}
|
||||
|
||||
void operator delete[](void *p) noexcept {
|
||||
deallocate<AllocationEvent::EVENT_DELETE_ARRAY>(p);
|
||||
}
|
||||
void operator delete(void *p, size_t size) noexcept {
|
||||
deallocate<AllocationEvent::EVENT_DELETE>(p);
|
||||
}
|
||||
|
||||
void operator delete[](void *p, size_t size) noexcept {
|
||||
deallocate<AllocationEvent::EVENT_DELETE_ARRAY>(p);
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace MemoryManagement {
|
||||
#if defined(__clang__)
|
||||
#define NO_SANITIZE __attribute__((no_sanitize("undefined")))
|
||||
#else
|
||||
#define NO_SANITIZE
|
||||
#endif
|
||||
|
||||
enum LeakDetectionMode {
|
||||
STANDARD,
|
||||
EXPECT_TO_LEAK,
|
||||
TURN_OFF_LEAK_DETECTION
|
||||
};
|
||||
|
||||
struct AllocationEvent { // NOLINT(clang-analyzer-optin.performance.Padding)
|
||||
enum {
|
||||
CallStackSize = 16
|
||||
};
|
||||
|
||||
enum EventType {
|
||||
EVENT_UNKNOWN,
|
||||
EVENT_NEW,
|
||||
EVENT_NEW_FAIL,
|
||||
EVENT_NEW_NOTHROW,
|
||||
EVENT_NEW_NOTHROW_FAIL,
|
||||
EVENT_NEW_ARRAY,
|
||||
EVENT_NEW_ARRAY_FAIL,
|
||||
EVENT_NEW_ARRAY_NOTHROW,
|
||||
EVENT_NEW_ARRAY_NOTHROW_FAIL,
|
||||
EVENT_DELETE,
|
||||
EVENT_DELETE_ARRAY
|
||||
};
|
||||
|
||||
EventType event;
|
||||
const void *address;
|
||||
size_t size;
|
||||
int frames;
|
||||
void *callstack[CallStackSize];
|
||||
bool fastLeakDetectionEnabled = false;
|
||||
};
|
||||
enum : int {
|
||||
maxEvents = 1024 * 1024,
|
||||
fastEvents = 1024 * 1024
|
||||
};
|
||||
extern AllocationEvent eventsAllocated[maxEvents];
|
||||
extern AllocationEvent eventsDeallocated[maxEvents];
|
||||
|
||||
extern void *fastEventsAllocated[maxEvents];
|
||||
extern void *fastEventsDeallocated[maxEvents];
|
||||
extern std::atomic<int> fastEventsAllocatedCount;
|
||||
extern std::atomic<int> fastEventsDeallocatedCount;
|
||||
extern std::atomic<int> fastLeaksDetectionMode;
|
||||
extern bool memsetNewAllocations;
|
||||
|
||||
extern size_t failingAllocation;
|
||||
extern std::atomic<size_t> numAllocations;
|
||||
extern std::atomic<size_t> indexAllocation;
|
||||
extern std::atomic<size_t> indexDeallocation;
|
||||
extern size_t breakOnAllocationEvent;
|
||||
extern size_t breakOnDeallocationEvent;
|
||||
extern bool logTraces;
|
||||
extern bool detailedAllocationLoggingActive;
|
||||
extern bool fastLeakDetectionEnabled;
|
||||
extern void (*deleteCallback)(void *);
|
||||
|
||||
constexpr auto nonfailingAllocation = static_cast<size_t>(-1);
|
||||
constexpr auto invalidLeakIndex = static_cast<size_t>(-1);
|
||||
|
||||
// capture allocations call stacks to print them during memory leak in ULTs
|
||||
constexpr bool captureCallStacks = false;
|
||||
|
||||
int detectLeaks();
|
||||
std::string printCallStack(const MemoryManagement::AllocationEvent &event);
|
||||
size_t enumerateLeak(size_t indexAllocationTop, size_t indexDeallocationTop, bool lookFromEnd, bool requireCallStack);
|
||||
|
||||
} // namespace MemoryManagement
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/simd_helper.h"
|
||||
#include "test.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
template <typename WALKER_TYPE>
|
||||
class GivenSimdSizeWhenGetSimdConfigCalledThenCorrectEnumReturned {
|
||||
public:
|
||||
static void TestBodyImpl() {
|
||||
uint32_t simd = 32;
|
||||
auto result = getSimdConfig<WALKER_TYPE>(simd);
|
||||
EXPECT_EQ(result, WALKER_TYPE::SIMD_SIZE::SIMD_SIZE_SIMD32);
|
||||
|
||||
simd = 16;
|
||||
result = getSimdConfig<WALKER_TYPE>(simd);
|
||||
EXPECT_EQ(result, WALKER_TYPE::SIMD_SIZE::SIMD_SIZE_SIMD16);
|
||||
|
||||
simd = 8;
|
||||
result = getSimdConfig<WALKER_TYPE>(simd);
|
||||
EXPECT_EQ(result, WALKER_TYPE::SIMD_SIZE::SIMD_SIZE_SIMD8);
|
||||
|
||||
simd = 1;
|
||||
result = getSimdConfig<WALKER_TYPE>(simd);
|
||||
EXPECT_EQ(result, WALKER_TYPE::SIMD_SIZE::SIMD_SIZE_SIMD32);
|
||||
}
|
||||
};
|
||||
} // namespace NEO
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/hash.h"
|
||||
#include "shared/source/helpers/string.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
TEST(StringHelpers, strncpy) {
|
||||
char dst[1024] = "";
|
||||
char src[1024] = "HelloWorld";
|
||||
|
||||
//preconditions
|
||||
ASSERT_EQ(sizeof(dst), sizeof(src));
|
||||
//String must be smaller than array capacity
|
||||
ASSERT_LT(strlen(src), sizeof(src));
|
||||
|
||||
auto ret = strncpy_s(nullptr, 1024, src, 1024);
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = strncpy_s(dst, 1024, nullptr, 1024);
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = strncpy_s(dst, 512, src, 1024);
|
||||
EXPECT_EQ(ret, -ERANGE);
|
||||
|
||||
memset(dst, 0, sizeof(dst));
|
||||
ret = strncpy_s(dst, 1024, src, strlen(src) / 2);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_EQ(0, memcmp(dst, src, strlen(src) / 2));
|
||||
for (size_t i = strlen(src) / 2; i < sizeof(dst); i++)
|
||||
EXPECT_EQ(0, dst[i]);
|
||||
|
||||
memset(dst, 0, sizeof(dst));
|
||||
ret = strncpy_s(dst, strlen(src) / 2, src, strlen(src) / 2);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_EQ(0, memcmp(dst, src, strlen(src) / 2));
|
||||
for (size_t i = strlen(src) / 2; i < sizeof(dst); i++)
|
||||
EXPECT_EQ(0, dst[i]);
|
||||
|
||||
strncpy_s(dst, 1024, src, 1024);
|
||||
EXPECT_EQ(0, memcmp(dst, src, strlen(src)));
|
||||
for (size_t i = strlen(src); i < sizeof(dst); i++)
|
||||
EXPECT_EQ(0, dst[i]);
|
||||
}
|
||||
|
||||
TEST(StringHelpers, memmove) {
|
||||
char dst[1024] = "";
|
||||
char src[1024] = "HelloWorld";
|
||||
|
||||
ASSERT_EQ(sizeof(dst), sizeof(src));
|
||||
|
||||
auto ret = memmove_s(nullptr, sizeof(dst), src, sizeof(src));
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = memmove_s(dst, sizeof(dst), nullptr, sizeof(src));
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = memmove_s(dst, sizeof(src) / 2, src, sizeof(src));
|
||||
EXPECT_EQ(ret, -ERANGE);
|
||||
|
||||
memset(dst, 0, sizeof(dst));
|
||||
ret = memmove_s(dst, sizeof(dst), src, sizeof(src));
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_EQ(0, memcmp(dst, src, sizeof(dst)));
|
||||
}
|
||||
|
||||
TEST(StringHelpers, strcpy) {
|
||||
char dst[1024] = "";
|
||||
char src[1024] = "HelloWorld";
|
||||
|
||||
ASSERT_EQ(sizeof(dst), sizeof(src));
|
||||
|
||||
auto ret = strcpy_s(nullptr, 0, src);
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = strcpy_s(nullptr, sizeof(dst), src);
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = strcpy_s(nullptr, 0, nullptr);
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = strcpy_s(nullptr, sizeof(dst), nullptr);
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = strcpy_s(dst, 0, nullptr);
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = strcpy_s(dst, strlen(src) / 2, src);
|
||||
EXPECT_EQ(ret, -ERANGE);
|
||||
|
||||
ret = strcpy_s(dst, strlen(src), src);
|
||||
EXPECT_EQ(ret, -ERANGE);
|
||||
|
||||
char pattern = 0x5a;
|
||||
memset(dst, pattern, sizeof(dst));
|
||||
ret = strcpy_s(dst, sizeof(dst), src);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_EQ(0, memcmp(dst, src, strlen(src)));
|
||||
EXPECT_EQ(0, dst[strlen(src)]);
|
||||
for (size_t i = strlen(src) + 1; i < sizeof(dst); i++)
|
||||
EXPECT_EQ(pattern, dst[i]);
|
||||
}
|
||||
|
||||
TEST(StringHelpers, strnlen) {
|
||||
char src[1024] = "HelloWorld";
|
||||
|
||||
auto ret = strnlen_s(nullptr, sizeof(src));
|
||||
EXPECT_EQ(ret, 0u);
|
||||
|
||||
ret = strnlen_s(src, 0);
|
||||
EXPECT_EQ(ret, 0u);
|
||||
|
||||
ret = strnlen_s(src, sizeof(src));
|
||||
EXPECT_EQ(ret, strlen(src));
|
||||
}
|
||||
|
||||
TEST(StringHelpers, memcpy) {
|
||||
char dst[1024] = "";
|
||||
char src[1024] = "HelloWorld";
|
||||
|
||||
//preconditions
|
||||
ASSERT_EQ(sizeof(dst), sizeof(src));
|
||||
//String must be smaller than array capacity
|
||||
ASSERT_LT(strlen(src), sizeof(src));
|
||||
|
||||
auto ret = memcpy_s(nullptr, sizeof(dst), src, sizeof(src));
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = memcpy_s(dst, sizeof(dst), nullptr, sizeof(src));
|
||||
EXPECT_EQ(ret, -EINVAL);
|
||||
|
||||
ret = memcpy_s(dst, sizeof(dst) / 2, src, sizeof(src));
|
||||
EXPECT_EQ(ret, -ERANGE);
|
||||
|
||||
memset(dst, 0, sizeof(dst));
|
||||
ret = memcpy_s(dst, sizeof(dst), src, strlen(src) / 2);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_EQ(0, memcmp(dst, src, strlen(src) / 2));
|
||||
for (size_t i = strlen(src) / 2; i < sizeof(dst); i++)
|
||||
EXPECT_EQ(0, dst[i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/hash.h"
|
||||
#include "opencl/source/helpers/string_helpers.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using NEO::Hash;
|
||||
|
||||
TEST(CreateCombinedStrings, singleString) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char srcString[] = "HelloWorld";
|
||||
const char *pSrcString = srcString;
|
||||
auto srcStrings = &pSrcString;
|
||||
size_t lengths = strlen(srcString);
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
1,
|
||||
srcStrings,
|
||||
&lengths);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(lengths + 1, dstStringSizeInBytes);
|
||||
|
||||
EXPECT_EQ(0, strcmp(srcString, dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, SingleStringWithNullLengthNoCrash) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char srcString[] = "HelloWorld";
|
||||
const char *pSrcString = srcString;
|
||||
auto srcStrings = &pSrcString;
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
1,
|
||||
srcStrings,
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, strcmp(srcString, dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, SingleStringWithZeroLengthNoCrash) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char srcString[] = "HelloWorld";
|
||||
const char *pSrcString = srcString;
|
||||
auto srcStrings = &pSrcString;
|
||||
size_t lengths = 0;
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
1,
|
||||
srcStrings,
|
||||
&lengths);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, strcmp(srcString, dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, multiString) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char *srcString[] = {"HelloWorld", "dlroWolleH"};
|
||||
std::string combined(srcString[0]);
|
||||
combined += srcString[1];
|
||||
|
||||
auto srcStrings = &srcString[0];
|
||||
size_t lengths[2] = {strlen(srcString[0]), strlen(srcString[1])};
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
2,
|
||||
srcStrings,
|
||||
lengths);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, strcmp(combined.c_str(), dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, multiStringWithNullLengthNoCrash) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char *srcString[] = {"HelloWorld", "dlroWolleH"};
|
||||
std::string combined(srcString[0]);
|
||||
combined += srcString[1];
|
||||
auto srcStrings = &srcString[0];
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
2,
|
||||
srcStrings,
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, strcmp(combined.c_str(), dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, multiStringWithZeroLengthNoCrash) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char *srcString[] = {"HelloWorld", "dlroWolleH"};
|
||||
std::string combined(srcString[0]);
|
||||
combined += srcString[1];
|
||||
auto srcStrings = &srcString[0];
|
||||
size_t lengths[2] = {0, strlen(srcString[1])};
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
2,
|
||||
srcStrings,
|
||||
lengths);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, strcmp(combined.c_str(), dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, GivenMultipleStringWhichOneContainsAndErrorAndSizeThatForcesDriverToOmitTheErorrThenProgramSourceDoesntContainErrorString) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char *srcString[] = {"HelloWorld", "dlroWolleHBABA"};
|
||||
const char *expString[] = {"HelloWorld", "dlroWolleH"};
|
||||
size_t lengths[2] = {0, strlen(expString[1])};
|
||||
std::string combined(expString[0]);
|
||||
combined += expString[1];
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
2,
|
||||
srcString,
|
||||
lengths);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, strcmp(combined.c_str(), dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, negativeScenarios) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char *srcString[] = {"HelloWorld", "dlroWolleH"};
|
||||
std::string combined(srcString[0]);
|
||||
combined += srcString[1];
|
||||
const char *srcStrings[2] = {srcString[0], srcString[1]};
|
||||
size_t lengths[2] = {0, strlen(srcString[1])};
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
0,
|
||||
srcStrings,
|
||||
lengths);
|
||||
EXPECT_EQ(CL_INVALID_VALUE, retVal);
|
||||
|
||||
retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
1,
|
||||
nullptr,
|
||||
lengths);
|
||||
EXPECT_EQ(CL_INVALID_VALUE, retVal);
|
||||
|
||||
srcStrings[0] = nullptr;
|
||||
retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
2,
|
||||
srcStrings,
|
||||
lengths);
|
||||
EXPECT_EQ(CL_INVALID_VALUE, retVal);
|
||||
}
|
||||
|
||||
TEST(CreateCombinedStrings, GivenMultipleStringThatCountIsHigherThenMaximalStackSizeSizesWhenAskedForCombinedThenProperStringIsRetruned) {
|
||||
std::string dstString;
|
||||
size_t dstStringSizeInBytes = 0;
|
||||
const char *defaultString = "hello";
|
||||
const char *srcString[maximalStackSizeSizes + 2];
|
||||
std::string combinedString;
|
||||
for (int i = 0; i < maximalStackSizeSizes + 2; i++) {
|
||||
srcString[i] = defaultString;
|
||||
combinedString += defaultString;
|
||||
}
|
||||
|
||||
auto retVal = createCombinedString(
|
||||
dstString,
|
||||
dstStringSizeInBytes,
|
||||
maximalStackSizeSizes + 2,
|
||||
srcString,
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, strcmp(combinedString.c_str(), dstString.c_str()));
|
||||
}
|
||||
|
||||
TEST(CreateHash, HashBuffers) {
|
||||
char pBuffer[128];
|
||||
memset(pBuffer, 0x23, sizeof(pBuffer));
|
||||
|
||||
// make sure we can get a hash and make sure we can get the same hash
|
||||
auto hash1 = Hash::hash(pBuffer, sizeof(pBuffer));
|
||||
auto hash2 = Hash::hash(pBuffer, sizeof(pBuffer));
|
||||
EXPECT_NE(0u, hash1);
|
||||
EXPECT_NE(0u, hash2);
|
||||
EXPECT_EQ(hash1, hash2);
|
||||
|
||||
// make sure that we get a different hash for different length/data
|
||||
auto hash3 = Hash::hash(pBuffer, sizeof(pBuffer) - 1);
|
||||
EXPECT_NE(0u, hash3);
|
||||
EXPECT_NE(hash2, hash3);
|
||||
}
|
||||
|
||||
TEST(CreateHash, unalignedLengths) {
|
||||
char pBuffer[] = {
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
|
||||
|
||||
// Use unaligned lengths. Wiggle the byte after the length
|
||||
// Shouldn't affect hash.
|
||||
for (auto length = 1u; length < sizeof(pBuffer); length++) {
|
||||
auto hash1 = Hash::hash(pBuffer, length);
|
||||
pBuffer[length]++;
|
||||
EXPECT_EQ(hash1, Hash::hash(pBuffer, length));
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
namespace NEO {
|
||||
struct UltHwConfig {
|
||||
bool mockedGetDevicesFuncResult = true;
|
||||
bool useHwCsr = false;
|
||||
bool useMockedGetDevicesFunc = true;
|
||||
bool forceOsAgnosticMemoryManager = true;
|
||||
|
||||
bool csrFailInitDirectSubmission = false;
|
||||
bool csrBaseCallDirectSubmissionAvailable = false;
|
||||
bool csrSuperBaseCallDirectSubmissionAvailable = false;
|
||||
};
|
||||
|
||||
extern UltHwConfig ultHwConfig;
|
||||
} // namespace NEO
|
||||
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helpers/ult_hw_config.h"
|
||||
|
||||
namespace NEO {
|
||||
UltHwConfig ultHwConfig{};
|
||||
} // namespace NEO
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/helpers/hw_helper.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
template <typename GfxFamily>
|
||||
struct UltMemorySynchronizationCommands : MemorySynchronizationCommands<GfxFamily> {
|
||||
using MemorySynchronizationCommands<GfxFamily>::getSizeForAdditonalSynchronization;
|
||||
|
||||
static size_t getExpectedPipeControlCount(const HardwareInfo &hwInfo) {
|
||||
return (MemorySynchronizationCommands<GfxFamily>::getSizeForPipeControlWithPostSyncOperation(hwInfo) -
|
||||
MemorySynchronizationCommands<GfxFamily>::getSizeForAdditonalSynchronization(hwInfo)) /
|
||||
sizeof(typename GfxFamily::PIPE_CONTROL);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace NEO
|
||||
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_CORE_IMAGE_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/image_surface_state_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/image_surface_state_tests.cpp
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_CORE_IMAGE_TESTS ${NEO_CORE_IMAGE_TESTS})
|
||||
|
||||
add_subdirectories()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user