2020-03-06 18:09:57 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019-2020 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-03-19 13:21:57 +08:00
|
|
|
#include "level_zero/core/source/event/event.h"
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
#include "shared/source/command_stream/command_stream_receiver_hw.h"
|
|
|
|
#include "shared/source/command_stream/csr_definitions.h"
|
|
|
|
#include "shared/source/debug_settings/debug_settings_manager.h"
|
|
|
|
#include "shared/source/device/device.h"
|
|
|
|
#include "shared/source/execution_environment/execution_environment.h"
|
|
|
|
#include "shared/source/execution_environment/root_device_environment.h"
|
2020-04-02 17:28:38 +08:00
|
|
|
#include "shared/source/helpers/constants.h"
|
2020-03-06 18:09:57 +08:00
|
|
|
#include "shared/source/helpers/string.h"
|
|
|
|
#include "shared/source/memory_manager/memory_manager.h"
|
|
|
|
#include "shared/source/memory_manager/memory_operations_handler.h"
|
|
|
|
#include "shared/source/utilities/cpuintrinsics.h"
|
|
|
|
|
2020-03-19 13:21:57 +08:00
|
|
|
#include "level_zero/core/source/device/device.h"
|
|
|
|
#include "level_zero/core/source/device/device_imp.h"
|
2020-03-06 18:09:57 +08:00
|
|
|
#include "level_zero/tools/source/metrics/metric.h"
|
|
|
|
|
|
|
|
#include <queue>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
namespace L0 {
|
|
|
|
|
|
|
|
struct EventPoolImp : public EventPool {
|
2020-07-29 17:45:54 +08:00
|
|
|
EventPoolImp(DriverHandle *driver, uint32_t numDevices, ze_device_handle_t *phDevices, uint32_t numEvents, ze_event_pool_flags_t flags) : numEvents(numEvents) {
|
|
|
|
if (flags & ZE_EVENT_POOL_FLAG_KERNEL_TIMESTAMP) {
|
2020-03-06 18:09:57 +08:00
|
|
|
isEventPoolUsedForTimestamp = true;
|
|
|
|
}
|
2020-03-17 06:47:18 +08:00
|
|
|
ze_device_handle_t hDevice;
|
|
|
|
if (numDevices > 0) {
|
|
|
|
hDevice = phDevices[0];
|
|
|
|
} else {
|
|
|
|
uint32_t count = 1;
|
|
|
|
ze_result_t result = driver->getDevice(&count, &hDevice);
|
|
|
|
|
|
|
|
UNRECOVERABLE_IF(result != ZE_RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
device = Device::fromHandle(hDevice);
|
|
|
|
|
2020-03-06 18:09:57 +08:00
|
|
|
NEO::AllocationProperties properties(
|
2020-07-07 21:27:11 +08:00
|
|
|
device->getRootDeviceIndex(), numEvents * eventSize,
|
2020-05-24 12:55:34 +08:00
|
|
|
isEventPoolUsedForTimestamp ? NEO::GraphicsAllocation::AllocationType::TIMESTAMP_PACKET_TAG_BUFFER
|
2020-07-08 18:09:05 +08:00
|
|
|
: NEO::GraphicsAllocation::AllocationType::BUFFER_HOST_MEMORY,
|
|
|
|
device->getNEODevice()->getDeviceBitfield());
|
2020-03-07 08:04:47 +08:00
|
|
|
properties.alignment = MemoryConstants::cacheLineSize;
|
2020-03-17 06:47:18 +08:00
|
|
|
eventPoolAllocation = driver->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties);
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
UNRECOVERABLE_IF(eventPoolAllocation == nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
~EventPoolImp() override {
|
|
|
|
device->getDriverHandle()->getMemoryManager()->freeGraphicsMemory(eventPoolAllocation);
|
|
|
|
eventPoolAllocation = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ze_result_t destroy() override;
|
|
|
|
|
|
|
|
ze_result_t getIpcHandle(ze_ipc_event_pool_handle_t *pIpcHandle) override;
|
|
|
|
|
|
|
|
ze_result_t closeIpcHandle() override;
|
|
|
|
|
|
|
|
ze_result_t createEvent(const ze_event_desc_t *desc, ze_event_handle_t *phEvent) override {
|
2020-07-07 21:27:11 +08:00
|
|
|
if (desc->index > (getNumEvents() - 1)) {
|
2020-03-11 14:19:06 +08:00
|
|
|
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
|
|
|
}
|
2020-03-06 18:09:57 +08:00
|
|
|
*phEvent = Event::create(this, desc, this->getDevice());
|
|
|
|
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t getEventSize() override { return eventSize; }
|
2020-07-07 21:27:11 +08:00
|
|
|
size_t getNumEvents() { return numEvents; }
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
Device *getDevice() override { return device; }
|
|
|
|
|
|
|
|
Device *device;
|
2020-07-07 21:27:11 +08:00
|
|
|
size_t numEvents;
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
protected:
|
2020-05-20 11:38:36 +08:00
|
|
|
const uint32_t eventSize = static_cast<uint32_t>(alignUp(sizeof(struct KernelTimestampEvent),
|
|
|
|
MemoryConstants::cacheLineSize));
|
2020-02-26 22:20:19 +08:00
|
|
|
const uint32_t eventAlignment = MemoryConstants::cacheLineSize;
|
2020-03-06 18:09:57 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
Event *Event::create(EventPool *eventPool, const ze_event_desc_t *desc, Device *device) {
|
|
|
|
auto event = new EventImp(eventPool, desc->index, device);
|
|
|
|
UNRECOVERABLE_IF(event == nullptr);
|
|
|
|
|
|
|
|
if (eventPool->isEventPoolUsedForTimestamp) {
|
|
|
|
event->isTimestampEvent = true;
|
|
|
|
}
|
|
|
|
|
2020-07-07 21:27:11 +08:00
|
|
|
uint64_t baseHostAddr = reinterpret_cast<uint64_t>(eventPool->getAllocation().getUnderlyingBuffer());
|
|
|
|
event->hostAddress = reinterpret_cast<void *>(baseHostAddr + (desc->index * eventPool->getEventSize()));
|
|
|
|
event->gpuAddress = eventPool->getAllocation().getGpuAddress() + (desc->index * eventPool->getEventSize());
|
|
|
|
|
2020-03-06 18:09:57 +08:00
|
|
|
event->signalScope = desc->signal;
|
|
|
|
event->waitScope = desc->wait;
|
2020-04-21 23:10:00 +08:00
|
|
|
event->csr = static_cast<DeviceImp *>(device)->neoDevice->getDefaultEngine().commandStreamReceiver;
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
event->reset();
|
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
|
|
|
NEO::GraphicsAllocation &Event::getAllocation() {
|
|
|
|
auto eventImp = static_cast<EventImp *>(this);
|
|
|
|
|
|
|
|
return eventImp->eventPool->getAllocation();
|
|
|
|
}
|
|
|
|
|
|
|
|
ze_result_t Event::destroy() {
|
|
|
|
delete this;
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-09-03 15:06:11 +08:00
|
|
|
ze_result_t EventImp::queryStatus() {
|
|
|
|
uint64_t *hostAddr = static_cast<uint64_t *>(hostAddress);
|
|
|
|
uint32_t queryVal = Event::STATE_CLEARED;
|
|
|
|
if (metricStreamer != nullptr) {
|
|
|
|
*hostAddr = metricStreamer->getNotificationState();
|
|
|
|
}
|
|
|
|
this->csr->downloadAllocations();
|
|
|
|
if (isTimestampEvent) {
|
|
|
|
auto baseAddr = reinterpret_cast<uint64_t>(hostAddress);
|
|
|
|
auto timeStampAddress = baseAddr + offsetof(KernelTimestampEvent, contextEnd);
|
|
|
|
hostAddr = reinterpret_cast<uint64_t *>(timeStampAddress);
|
|
|
|
}
|
|
|
|
memcpy_s(static_cast<void *>(&queryVal), sizeof(uint32_t), static_cast<void *>(hostAddr), sizeof(uint32_t));
|
|
|
|
return queryVal == Event::STATE_CLEARED ? ZE_RESULT_NOT_READY : ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-04-09 03:44:14 +08:00
|
|
|
ze_result_t EventImp::hostEventSetValueTimestamps(uint32_t eventVal) {
|
2020-03-06 18:09:57 +08:00
|
|
|
|
2020-04-29 10:11:59 +08:00
|
|
|
auto baseAddr = reinterpret_cast<uint64_t>(hostAddress);
|
|
|
|
auto signalScopeFlag = this->signalScope;
|
2020-03-06 18:09:57 +08:00
|
|
|
|
2020-04-29 10:11:59 +08:00
|
|
|
auto eventTsSetFunc = [&](auto tsAddr) {
|
|
|
|
auto tsptr = reinterpret_cast<void *>(tsAddr);
|
|
|
|
memcpy_s(tsptr, sizeof(uint32_t), static_cast<void *>(&eventVal), sizeof(uint32_t));
|
2020-07-29 17:45:54 +08:00
|
|
|
if (!signalScopeFlag) {
|
2020-03-06 18:09:57 +08:00
|
|
|
NEO::CpuIntrinsics::clFlush(tsptr);
|
|
|
|
}
|
2020-04-29 10:11:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, contextStart));
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalStart));
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, contextEnd));
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalEnd));
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-04-09 03:44:14 +08:00
|
|
|
ze_result_t EventImp::hostEventSetValue(uint32_t eventVal) {
|
2020-03-06 18:09:57 +08:00
|
|
|
if (isTimestampEvent) {
|
2020-04-29 10:11:59 +08:00
|
|
|
return hostEventSetValueTimestamps(eventVal);
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
auto hostAddr = static_cast<uint64_t *>(hostAddress);
|
|
|
|
UNRECOVERABLE_IF(hostAddr == nullptr);
|
2020-05-08 07:02:30 +08:00
|
|
|
memcpy_s(static_cast<void *>(hostAddr), sizeof(uint32_t), static_cast<void *>(&eventVal), sizeof(uint32_t));
|
2020-03-06 18:09:57 +08:00
|
|
|
|
2020-09-07 20:31:23 +08:00
|
|
|
NEO::CpuIntrinsics::clFlush(hostAddr);
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
ze_result_t EventImp::hostSignal() {
|
|
|
|
return hostEventSetValue(Event::STATE_SIGNALED);
|
|
|
|
}
|
|
|
|
|
2020-07-29 17:45:54 +08:00
|
|
|
ze_result_t EventImp::hostSynchronize(uint64_t timeout) {
|
2020-03-06 18:09:57 +08:00
|
|
|
std::chrono::high_resolution_clock::time_point time1, time2;
|
2020-07-29 17:45:54 +08:00
|
|
|
uint64_t timeDiff = 0;
|
2020-03-06 18:09:57 +08:00
|
|
|
ze_result_t ret = ZE_RESULT_NOT_READY;
|
|
|
|
|
2020-04-21 23:10:00 +08:00
|
|
|
if (this->csr->getType() == NEO::CommandStreamReceiverType::CSR_AUB) {
|
2020-03-06 18:09:57 +08:00
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timeout == 0) {
|
|
|
|
return queryStatus();
|
|
|
|
}
|
|
|
|
|
|
|
|
time1 = std::chrono::high_resolution_clock::now();
|
|
|
|
while (true) {
|
|
|
|
ret = queryStatus();
|
|
|
|
if (ret == ZE_RESULT_SUCCESS) {
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::this_thread::yield();
|
|
|
|
NEO::CpuIntrinsics::pause();
|
|
|
|
|
|
|
|
if (timeout == std::numeric_limits<uint32_t>::max()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
time2 = std::chrono::high_resolution_clock::now();
|
|
|
|
timeDiff = std::chrono::duration_cast<std::chrono::nanoseconds>(time2 - time1).count();
|
|
|
|
|
|
|
|
if (timeDiff >= timeout) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ze_result_t EventImp::reset() {
|
|
|
|
return hostEventSetValue(Event::STATE_INITIAL);
|
|
|
|
}
|
|
|
|
|
2020-07-29 20:25:20 +08:00
|
|
|
ze_result_t EventImp::queryKernelTimestamp(ze_kernel_timestamp_result_t *dstptr) {
|
|
|
|
auto baseAddr = reinterpret_cast<uint64_t>(hostAddress);
|
|
|
|
constexpr uint64_t tsMask = (1ull << 32) - 1;
|
|
|
|
uint64_t tsData = Event::STATE_INITIAL & tsMask;
|
|
|
|
ze_kernel_timestamp_result_t &result = *dstptr;
|
|
|
|
|
|
|
|
// Ensure timestamps have been written
|
|
|
|
if (queryStatus() != ZE_RESULT_SUCCESS) {
|
2020-09-03 15:06:11 +08:00
|
|
|
return ZE_RESULT_NOT_READY;
|
2020-07-29 20:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
auto eventTsSetFunc = [&](auto tsAddr, uint64_t ×tampField) {
|
|
|
|
memcpy_s(static_cast<void *>(&tsData), sizeof(uint32_t), reinterpret_cast<void *>(tsAddr), sizeof(uint32_t));
|
|
|
|
|
|
|
|
tsData &= tsMask;
|
|
|
|
memcpy_s(&(timestampField), sizeof(uint64_t), static_cast<void *>(&tsData), sizeof(uint64_t));
|
|
|
|
};
|
|
|
|
|
2020-09-03 15:06:11 +08:00
|
|
|
if (!NEO::HwHelper::get(device->getHwInfo().platform.eRenderCoreFamily).useOnlyGlobalTimestamps()) {
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, contextStart), result.context.kernelStart);
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalStart), result.global.kernelStart);
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, contextEnd), result.context.kernelEnd);
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalEnd), result.global.kernelEnd);
|
|
|
|
} else {
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalStart), result.context.kernelStart);
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalStart), result.global.kernelStart);
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalEnd), result.context.kernelEnd);
|
|
|
|
eventTsSetFunc(baseAddr + offsetof(KernelTimestampEvent, globalEnd), result.global.kernelEnd);
|
|
|
|
}
|
2020-07-29 20:25:20 +08:00
|
|
|
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-03-17 06:47:18 +08:00
|
|
|
EventPool *EventPool::create(DriverHandle *driver, uint32_t numDevices,
|
|
|
|
ze_device_handle_t *phDevices,
|
|
|
|
const ze_event_pool_desc_t *desc) {
|
|
|
|
return new EventPoolImp(driver, numDevices, phDevices, desc->count, desc->flags);
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ze_result_t EventPoolImp::getIpcHandle(ze_ipc_event_pool_handle_t *pIpcHandle) {
|
|
|
|
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ze_result_t EventPoolImp::closeIpcHandle() { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; }
|
|
|
|
|
|
|
|
ze_result_t EventPoolImp::destroy() {
|
|
|
|
delete this;
|
|
|
|
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace L0
|