Adding Command container implementation

Change-Id: Ic2c4b9128fa0275fd10db6e37b89a1f36aee60bc
Signed-off-by: Maciej Plewka <maciej.plewka@intel.com>
This commit is contained in:
Maciej Plewka 2019-11-18 15:12:22 +01:00 committed by sys_ocldev
parent caa16ea81b
commit 49cde627c4
10 changed files with 409 additions and 0 deletions

View File

@ -0,0 +1,13 @@
#
# Copyright (C) 2019 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
set(NEO_CORE_COMMAND_CONTAINER
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/cmdcontainer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/cmdcontainer.h
)
set_property(GLOBAL PROPERTY NEO_CORE_COMMAND_CONTAINER ${NEO_CORE_COMMAND_CONTAINER})

View File

@ -0,0 +1,115 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/command_container/cmdcontainer.h"
#include "core/command_stream/linear_stream.h"
#include "core/helpers/debug_helpers.h"
#include "core/helpers/heap_helper.h"
#include "runtime/command_stream/command_stream_receiver.h"
#include "runtime/device/device.h"
#include "runtime/indirect_heap/indirect_heap.h"
#include "runtime/memory_manager/memory_manager.h"
#include <cassert>
namespace NEO {
CommandContainer::~CommandContainer() {
if (!device) {
DEBUG_BREAK_IF(device);
return;
}
auto memoryManager = device->getMemoryManager();
memoryManager->freeGraphicsMemory(cmdBufferAllocation);
for (auto allocationIndirectHeap : allocationIndirectHeaps) {
heapHelper->storeHeapAllocation(allocationIndirectHeap);
}
residencyContainer.clear();
deallocationContainer.clear();
}
bool CommandContainer::initialize(Device *device) {
if (!device) {
DEBUG_BREAK_IF(device);
return false;
}
this->device = device;
heapHelper = std::unique_ptr<HeapHelper>(new HeapHelper(device->getMemoryManager(), device->getDefaultEngine().commandStreamReceiver->getInternalAllocationStorage(), device->getNumAvailableDevices() > 1u));
size_t alignedSize = alignUp<size_t>(totalCmdBufferSize, MemoryConstants::pageSize64k);
NEO::AllocationProperties properties{device->getRootDeviceIndex(), true /* allocateMemory*/, alignedSize,
GraphicsAllocation::AllocationType::INTERNAL_HOST_MEMORY,
(device->getNumAvailableDevices() > 1u) /* multiOsContextCapable */,
false,
NEO::AllocationProperties::noDeviceSpecified};
cmdBufferAllocation = device->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties);
UNRECOVERABLE_IF(!cmdBufferAllocation);
commandStream = std::unique_ptr<LinearStream>(new LinearStream(cmdBufferAllocation->getUnderlyingBuffer(),
defaultListCmdBufferSize));
commandStream->replaceGraphicsAllocation(cmdBufferAllocation);
addToResidencyContainer(cmdBufferAllocation);
size_t heapSize = 65536u;
for (auto &allocationIndirectHeap : allocationIndirectHeaps) {
allocationIndirectHeap = heapHelper->getHeapAllocation(heapSize, alignedSize, device->getRootDeviceIndex());
UNRECOVERABLE_IF(!allocationIndirectHeap);
residencyContainer.push_back(allocationIndirectHeap);
}
uint32_t index = 0;
for (auto &indirectHeap : indirectHeaps) {
auto alloc = allocationIndirectHeaps[index++];
indirectHeap = std::make_unique<IndirectHeap>(alloc);
}
instructionHeapBaseAddress = device->getMemoryManager()->getInternalHeapBaseAddress(0);
return true;
}
void CommandContainer::addToResidencyContainer(NEO::GraphicsAllocation *alloc) {
if (alloc == nullptr) {
DEBUG_BREAK_IF(true);
return;
}
auto end = this->residencyContainer.end();
bool isUnique = (end == std::find(this->residencyContainer.begin(), end, alloc));
if (isUnique == false) {
return;
}
this->residencyContainer.push_back(alloc);
}
void CommandContainer::reset() {
dirtyHeaps = std::numeric_limits<uint32_t>::max();
slmSize = std::numeric_limits<uint32_t>::max();
getResidencyContainer().clear();
getDeallocationContainer().clear();
commandStream->replaceBuffer(this->getCommandStream()->getCpuBase(),
defaultListCmdBufferSize);
addToResidencyContainer(commandStream->getGraphicsAllocation());
for (auto &indirectHeap : indirectHeaps) {
indirectHeap->replaceBuffer(indirectHeap->getCpuBase(),
indirectHeap->getMaxAvailableSpace());
addToResidencyContainer(indirectHeap->getGraphicsAllocation());
}
}
} // namespace NEO

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "core/helpers/heap_helper.h"
#include "core/helpers/non_copyable_or_moveable.h"
#include "runtime/command_stream/csr_definitions.h"
#include "runtime/indirect_heap/indirect_heap.h"
#include <cstdint>
#include <limits>
#include <memory>
#include <vector>
namespace NEO {
class Device;
class GraphicsAllocation;
class LinearStream;
using ResidencyContainer = std::vector<GraphicsAllocation *>;
using HeapType = IndirectHeap::Type;
class CommandContainer : public NonCopyableOrMovableClass {
public:
static constexpr size_t defaultListCmdBufferSize = MemoryConstants::kiloByte * 256;
static constexpr size_t totalCmdBufferSize =
defaultListCmdBufferSize +
MemoryConstants::cacheLineSize +
NEO::CSRequirements::csOverfetchSize;
CommandContainer() = default;
GraphicsAllocation *getCmdBufferAllocation() { return cmdBufferAllocation; }
ResidencyContainer &getResidencyContainer() { return residencyContainer; }
std::vector<GraphicsAllocation *> &getDeallocationContainer() { return deallocationContainer; }
void addToResidencyContainer(GraphicsAllocation *alloc);
LinearStream *getCommandStream() { return commandStream.get(); }
IndirectHeap *getIndirectHeap(HeapType heapType) { return indirectHeaps[heapType].get(); }
HeapHelper *getHeapHelper() { return heapHelper.get(); }
GraphicsAllocation *getIndirectHeapAllocation(HeapType heapType) { return allocationIndirectHeaps[heapType]; }
void setIndirectHeapAllocation(HeapType heapType, GraphicsAllocation *allocation) { allocationIndirectHeaps[heapType] = allocation; }
void setCmdBufferAllocation(GraphicsAllocation *allocation) { cmdBufferAllocation = allocation; }
uint64_t getInstructionHeapBaseAddress() const { return instructionHeapBaseAddress; }
bool initialize(Device *device);
virtual ~CommandContainer();
uint32_t dirtyHeaps = std::numeric_limits<uint32_t>::max();
uint32_t slmSize = std::numeric_limits<uint32_t>::max();
Device *getDevice() const { return device; }
void reset();
protected:
Device *device = nullptr;
std::unique_ptr<HeapHelper> heapHelper;
GraphicsAllocation *cmdBufferAllocation = nullptr;
GraphicsAllocation *allocationIndirectHeaps[HeapType::NUM_TYPES] = {};
uint64_t instructionHeapBaseAddress = 0u;
std::unique_ptr<LinearStream> commandStream;
std::unique_ptr<IndirectHeap> indirectHeaps[HeapType::NUM_TYPES] = {};
ResidencyContainer residencyContainer;
std::vector<GraphicsAllocation *> deallocationContainer;
};
} // namespace NEO

View File

@ -16,6 +16,8 @@ set(NEO_CORE_HELPERS
${CMAKE_CURRENT_SOURCE_DIR}/file_io.cpp
${CMAKE_CURRENT_SOURCE_DIR}/file_io.h
${CMAKE_CURRENT_SOURCE_DIR}/hash.h
${CMAKE_CURRENT_SOURCE_DIR}/heap_helper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/heap_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/hw_helper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hw_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/hw_helper_base.inl

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/helpers/heap_helper.h"
#include "core/memory_manager/graphics_allocation.h"
#include "runtime/memory_manager/internal_allocation_storage.h"
#include "runtime/memory_manager/memory_manager.h"
namespace NEO {
GraphicsAllocation *HeapHelper::getHeapAllocation(size_t heapSize, size_t alignment, uint32_t rootDeviceIndex) {
auto allocation = this->storageForReuse->obtainReusableAllocation(heapSize, GraphicsAllocation::AllocationType::INTERNAL_HEAP);
if (allocation) {
return allocation.release();
}
NEO::AllocationProperties properties{rootDeviceIndex, true /* allocateMemory*/, alignment,
GraphicsAllocation::AllocationType::INTERNAL_HEAP,
isMultiOsContextCapable /* multiOsContextCapable */,
false,
NEO::AllocationProperties::noDeviceSpecified};
return this->memManager->allocateGraphicsMemoryWithProperties(properties);
}
void HeapHelper::storeHeapAllocation(GraphicsAllocation *heapAllocation) {
this->storageForReuse->storeAllocation(std::unique_ptr<NEO::GraphicsAllocation>(heapAllocation), NEO::AllocationUsage::REUSABLE_ALLOCATION);
}
} // namespace NEO

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <stddef.h>
#include <stdint.h>
namespace NEO {
class MemoryManager;
class GraphicsAllocation;
class InternalAllocationStorage;
class HeapHelper {
public:
HeapHelper(MemoryManager *memManager, InternalAllocationStorage *storageForReuse, bool isMultiOsContextCapable) : storageForReuse(storageForReuse),
memManager(memManager),
isMultiOsContextCapable(isMultiOsContextCapable) {}
GraphicsAllocation *getHeapAllocation(size_t heapSize, size_t alignment, uint32_t rootDeviceIndex);
void storeHeapAllocation(GraphicsAllocation *heapAllocation);
protected:
InternalAllocationStorage *storageForReuse = nullptr;
MemoryManager *memManager = nullptr;
bool isMultiOsContextCapable = false;
};
} // namespace NEO

View File

@ -0,0 +1,12 @@
#
# Copyright (C) 2019 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
set(NEO_COMMAND_CONTAINER_TESTS
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/command_container_tests.cpp
)
set_property(GLOBAL PROPERTY NEO_COMMAND_CONTAINER_TESTS ${NEO_COMMAND_CONTAINER_TESTS})
add_subdirectories()

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/command_container/cmdcontainer.h"
#include "test.h"
#include "unit_tests/fixtures/device_fixture.h"
#include "unit_tests/mocks/mock_graphics_allocation.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();
}
};
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_NE(cmdContainer.getCmdBufferAllocation(), nullptr);
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, givenCommandContainerWhenSettingCommandBufferAllocationThenAllocationIsSet) {
CommandContainer cmdContainer;
MockGraphicsAllocation mockAllocation;
cmdContainer.setCmdBufferAllocation(&mockAllocation);
EXPECT_EQ(cmdContainer.getCmdBufferAllocation(), &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);
}

View File

@ -7,6 +7,7 @@
target_sources(${NEO_STATIC_LIB_NAME} PRIVATE ${NEO_SOURCE_DIR}/runtime/core_files.cmake)
append_sources_from_properties(NEO_CORE_SOURCES
NEO_CORE_COMMAND_CONTAINER
NEO_CORE_COMMAND_STREAM
NEO_CORE_EXECUTION_ENVIRONMENT
NEO_CORE_GMM_HELPER

View File

@ -556,4 +556,7 @@ elseif(USE_ULT_PCH)
DEPENDS ${UltPchBinary})
endif()
get_property(NEO_COMMAND_CONTAINER_TESTS GLOBAL PROPERTY NEO_COMMAND_CONTAINER_TESTS)
target_sources(igdrcl_tests PRIVATE ${NEO_COMMAND_CONTAINER_TESTS})
# Dont add any sources below PCH logic. This is to keep PCH dependencies correctly without creating new target