Adding Command container implementation
Change-Id: Ic2c4b9128fa0275fd10db6e37b89a1f36aee60bc Signed-off-by: Maciej Plewka <maciej.plewka@intel.com>
This commit is contained in:
parent
caa16ea81b
commit
49cde627c4
|
@ -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})
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue