/* * Copyright (C) 2018 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "runtime/helpers/kernel_commands.h" #include "runtime/helpers/properties_helper.h" #include #include #include #include namespace OCLRT { class CommandStreamReceiver; class LinearStream; template struct TagNode; namespace TimestampPacketSizeControl { constexpr uint32_t preferedChunkCount = 16u; } #pragma pack(1) class TimestampPacket { public: TimestampPacket() { initialize(); } enum class DataIndex : uint32_t { ContextStart = 0, GlobalStart, ContextEnd, GlobalEnd, Max }; enum class WriteOperationType : uint32_t { BeforeWalker, AfterWalker }; bool canBeReleased() const { return data[static_cast(DataIndex::ContextEnd)] != 1 && data[static_cast(DataIndex::GlobalEnd)] != 1 && implicitDependenciesCount.load() == 0; } uint64_t pickAddressForDataWrite(DataIndex operationType) const { auto index = static_cast(operationType); return reinterpret_cast(&data[index]); } void initialize() { for (auto index = 0u; index < data.size(); index++) { data[index] = 1; } implicitDependenciesCount.store(0); } void incImplicitDependenciesCount() { implicitDependenciesCount++; } uint64_t pickImplicitDependenciesCountWriteAddress() const { return reinterpret_cast(&implicitDependenciesCount); } protected: std::array(DataIndex::Max) * TimestampPacketSizeControl::preferedChunkCount> data; std::atomic implicitDependenciesCount; }; #pragma pack() static_assert(((static_cast(TimestampPacket::DataIndex::Max) * TimestampPacketSizeControl::preferedChunkCount + 1) * sizeof(uint32_t)) == sizeof(TimestampPacket), "This structure is consumed by GPU and has to follow specific restrictions for padding and size"); struct TimestampPacketHelper { template static void programSemaphoreWithImplicitDependency(LinearStream &cmdStream, TimestampPacket ×tampPacket) { using MI_ATOMIC = typename GfxFamily::MI_ATOMIC; auto compareAddress = timestampPacket.pickAddressForDataWrite(TimestampPacket::DataIndex::ContextEnd); auto dependenciesCountAddress = timestampPacket.pickImplicitDependenciesCountWriteAddress(); KernelCommandsHelper::programMiSemaphoreWait(cmdStream, compareAddress, 1); timestampPacket.incImplicitDependenciesCount(); KernelCommandsHelper::programMiAtomic(cmdStream, dependenciesCountAddress, MI_ATOMIC::ATOMIC_OPCODES::ATOMIC_4B_DECREMENT, MI_ATOMIC::DATA_SIZE::DATA_SIZE_DWORD); } }; class TimestampPacketContainer : public NonCopyableOrMovableClass { public: using Node = TagNode; TimestampPacketContainer() = default; MOCKABLE_VIRTUAL ~TimestampPacketContainer(); const std::vector &peekNodes() const { return timestampPacketNodes; } void add(Node *timestampPacketNode); void swapNodes(TimestampPacketContainer ×tampPacketContainer); void assignAndIncrementNodesRefCounts(const TimestampPacketContainer &inputTimestampPacketContainer); void resolveDependencies(bool clearAllDependencies); void makeResident(CommandStreamReceiver &commandStreamReceiver); protected: std::vector timestampPacketNodes; }; } // namespace OCLRT