Preemption - SIP command programming

Change-Id: I4c7c805a77a9decb8f13d39055bfb2590209ca3e
This commit is contained in:
Chodor, Jaroslaw
2018-01-08 15:58:02 +01:00
committed by sys_ocldev
parent 6272c3ee65
commit d290955a57
28 changed files with 661 additions and 90 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -238,6 +238,13 @@ IndirectHeap &CommandQueue::getIndirectHeap(IndirectHeap::Type heapType,
minHeapSize -= MemoryConstants::pageSize;
}
size_t reservedSize = 0;
if (heapType == IndirectHeap::INSTRUCTION) {
reservedSize = alignUp(device->getCommandStreamReceiver().getInstructionHeapCmdStreamReceiverReservedSize(),
MemoryConstants::cacheLineSize);
}
minRequiredSize += reservedSize;
minRequiredSize = minRequiredSize ? std::max(minRequiredSize, minHeapSize) : 0;
minRequiredSize = minRequiredSize > 0 ? alignUp(minRequiredSize, MemoryConstants::cacheLineSize) : 0;
@ -255,6 +262,11 @@ IndirectHeap &CommandQueue::getIndirectHeap(IndirectHeap::Type heapType,
heap = new IndirectHeap(heapMemory);
heap->overrideMaxSize(minRequiredSize);
}
if (heapType == IndirectHeap::INSTRUCTION) {
device->getCommandStreamReceiver().initializeInstructionHeapCmdStreamReceiverReservedBlock(*heap);
heap->align(MemoryConstants::cacheLineSize);
}
}
return *heap;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -20,7 +20,10 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "runtime/built_ins/built_ins.h"
#include "runtime/command_stream/command_stream_receiver.h"
#include "runtime/command_stream/preemption.h"
#include "runtime/device/device.h"
#include "runtime/memory_manager/memory_manager.h"
#include "runtime/helpers/cache_policy.h"
#include "runtime/os_interface/os_interface.h"
@ -197,4 +200,13 @@ void CommandStreamReceiver::setRequiredScratchSize(uint32_t newRequiredScratchSi
requiredScratchSize = newRequiredScratchSize;
}
}
size_t CommandStreamReceiver::getInstructionHeapCmdStreamReceiverReservedSize() const {
return PreemptionHelper::getInstructionHeapSipKernelReservedSize(*memoryManager->device);
}
void CommandStreamReceiver::initializeInstructionHeapCmdStreamReceiverReservedBlock(LinearStream &ih) const {
return PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(ih, *memoryManager->device);
}
} // namespace OCLRT

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -109,6 +109,12 @@ class CommandStreamReceiver {
virtual void waitForTaskCountWithKmdNotifyFallback(uint32_t taskCountToWait, FlushStamp flushStampToWait) = 0;
MOCKABLE_VIRTUAL bool waitForCompletionWithTimeout(bool enableTimeout, int64_t timeoutMs, uint32_t taskCountToWait);
// returns size of block that needs to be reserved at the beginning of each instruction heap for CommandStreamReceiver
MOCKABLE_VIRTUAL size_t getInstructionHeapCmdStreamReceiverReservedSize() const;
// allows CommandStreamReceiver to prepopulate reserved block in instruction heap
MOCKABLE_VIRTUAL void initializeInstructionHeapCmdStreamReceiverReservedBlock(LinearStream &ih) const;
protected:
// taskCount - # of tasks submitted
uint32_t taskCount = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -61,14 +61,14 @@ class CommandStreamReceiverHw : public CommandStreamReceiver {
static void addBatchBufferStart(MI_BATCH_BUFFER_START *commandBufferMemory, uint64_t startAddress);
static void alignToCacheLine(LinearStream &commandStream);
size_t getRequiredCsrSize();
size_t getRequiredCmdStreamSize(const DispatchFlags &dispatchFlags);
size_t getCmdSizeForCoherency();
void programCoherency(LinearStream &csr, DispatchFlags &dispatchFlags);
void waitForTaskCountWithKmdNotifyFallback(uint32_t taskCountToWait, FlushStamp flushStampToWait) override;
protected:
void programPreemption(LinearStream &csr, DispatchFlags &dispatchFlags);
void programPreemption(LinearStream &csr, DispatchFlags &dispatchFlags, const LinearStream &ih);
void programL3(LinearStream &csr, DispatchFlags &dispatchFlags, uint32_t &newL3Config);
void programMediaSampler(LinearStream &csr, DispatchFlags &dispatchFlags);
void programPreamble(LinearStream &csr, DispatchFlags &dispatchFlags, uint32_t &newL3Config);
@ -93,5 +93,5 @@ class CommandStreamReceiverHw : public CommandStreamReceiver {
};
template <typename GfxFamily>
size_t getSizeRequiredPreambleCS(const HardwareInfo &hwInfo);
size_t getSizeRequiredPreambleCS(const Device &device);
} // namespace OCLRT

View File

@ -67,11 +67,11 @@ inline void CommandStreamReceiverHw<GfxFamily>::alignToCacheLine(LinearStream &c
}
template <typename GfxFamily>
size_t getSizeRequiredPreambleCS(const HardwareInfo &hwInfo) {
size_t getSizeRequiredPreambleCS(const Device &device) {
return sizeof(typename GfxFamily::MI_LOAD_REGISTER_IMM) +
sizeof(typename GfxFamily::PIPELINE_SELECT) +
sizeof(typename GfxFamily::PIPE_CONTROL) +
sizeof(typename GfxFamily::MEDIA_VFE_STATE) + PreambleHelper<GfxFamily>::getAdditionalCommandsSize(hwInfo);
sizeof(typename GfxFamily::MEDIA_VFE_STATE) + PreambleHelper<GfxFamily>::getAdditionalCommandsSize(device);
}
template <typename GfxFamily>
@ -163,11 +163,11 @@ CompletionStamp CommandStreamReceiverHw<GfxFamily>::flushTask(
csrSizeRequestFlags.preemptionRequestChanged = this->lastPreemptionMode != dispatchFlags.preemptionMode;
csrSizeRequestFlags.mediaSamplerConfigChanged = this->lastMediaSamplerConfig != dispatchFlags.mediaSamplerRequired;
auto &commandStreamCSR = this->getCS(getRequiredCsrSize());
auto &commandStreamCSR = this->getCS(getRequiredCmdStreamSize(dispatchFlags));
auto commandStreamStartCSR = commandStreamCSR.getUsed();
initPageTableManagerRegisters(commandStreamCSR);
programPreemption(commandStreamCSR, dispatchFlags);
programPreemption(commandStreamCSR, dispatchFlags, ih);
programCoherency(commandStreamCSR, dispatchFlags);
programL3(commandStreamCSR, dispatchFlags, newL3Config);
programMediaSampler(commandStreamCSR, dispatchFlags);
@ -491,8 +491,8 @@ uint64_t CommandStreamReceiverHw<GfxFamily>::getScratchPatchAddress() {
}
template <typename GfxFamily>
size_t CommandStreamReceiverHw<GfxFamily>::getRequiredCsrSize() {
size_t size = getSizeRequiredPreambleCS<GfxFamily>(hwInfo) +
size_t CommandStreamReceiverHw<GfxFamily>::getRequiredCmdStreamSize(const DispatchFlags &dispatchFlags) {
size_t size = getSizeRequiredPreambleCS<GfxFamily>(*memoryManager->device) +
sizeof(typename GfxFamily::STATE_BASE_ADDRESS) +
sizeof(PIPE_CONTROL) +
getRequiredPipeControlSize() +
@ -502,9 +502,8 @@ size_t CommandStreamReceiverHw<GfxFamily>::getRequiredCsrSize() {
}
size += getCmdSizeForCoherency();
if (csrSizeRequestFlags.preemptionRequestChanged) {
size += PreemptionHelper::getRequiredCmdStreamSize<GfxFamily>(memoryManager->device->getPreemptionMode());
}
size += PreemptionHelper::getRequiredCmdStreamSize<GfxFamily>(dispatchFlags.preemptionMode, this->lastPreemptionMode);
return alignUp(size, MemoryConstants::cacheLineSize);
}
@ -529,11 +528,11 @@ inline void CommandStreamReceiverHw<GfxFamily>::waitForTaskCountWithKmdNotifyFal
}
template <typename GfxFamily>
inline void CommandStreamReceiverHw<GfxFamily>::programPreemption(LinearStream &csr, DispatchFlags &dispatchFlags) {
if (csrSizeRequestFlags.preemptionRequestChanged) {
PreemptionHelper::programCmdStream<GfxFamily>(&csr, dispatchFlags.preemptionMode, preemptionCsrAllocation, nullptr);
this->lastPreemptionMode = dispatchFlags.preemptionMode;
}
inline void CommandStreamReceiverHw<GfxFamily>::programPreemption(LinearStream &csr, DispatchFlags &dispatchFlags,
const LinearStream &ih) {
PreemptionHelper::programCmdStream<GfxFamily>(csr, dispatchFlags.preemptionMode, this->lastPreemptionMode, preemptionCsrAllocation,
ih, *memoryManager->device);
this->lastPreemptionMode = dispatchFlags.preemptionMode;
}
template <typename GfxFamily>
@ -562,7 +561,7 @@ inline void CommandStreamReceiverHw<GfxFamily>::programMediaSampler(LinearStream
template <typename GfxFamily>
inline void CommandStreamReceiverHw<GfxFamily>::programPreamble(LinearStream &csr, DispatchFlags &dispatchFlags, uint32_t &newL3Config) {
if (!this->isPreambleSent) {
PreambleHelper<GfxFamily>::programPreamble(&csr, hwInfo, newL3Config, this->requiredThreadArbitrationPolicy);
PreambleHelper<GfxFamily>::programPreamble(&csr, *memoryManager->device, newL3Config, this->requiredThreadArbitrationPolicy, this->preemptionCsrAllocation);
this->isPreambleSent = true;
this->lastSentL3Config = newL3Config;
this->lastSentThreadAribtrationPolicy = this->requiredThreadArbitrationPolicy;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -20,8 +20,11 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "runtime/built_ins/built_ins.h"
#include "runtime/command_stream/preemption.h"
#include "runtime/device/device.h"
#include "runtime/helpers/dispatch_info.h"
#include "runtime/helpers/string.h"
#include "runtime/kernel/kernel.h"
namespace OCLRT {
@ -101,4 +104,37 @@ void PreemptionHelper::adjustDefaultPreemptionMode(RuntimeCapabilityTable &devic
}
}
size_t PreemptionHelper::getInstructionHeapSipKernelReservedSize(const Device &device) {
if (device.getPreemptionMode() != PreemptionMode::MidThread) {
return 0;
}
return BuiltIns::getInstance().getSipKernel(SipKernelType::Csr, device).getBinarySize();
}
void PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(LinearStream &ih, const Device &device) {
if (device.getPreemptionMode() != PreemptionMode::MidThread) {
return;
}
const SipKernel &sip = BuiltIns::getInstance().getSipKernel(SipKernelType::Csr, device);
size_t sipSize = sip.getBinarySize();
UNRECOVERABLE_IF(sipSize > ih.getAvailableSpace());
UNRECOVERABLE_IF(0 != ih.getUsed());
void *blockForSip = ih.getSpace(sipSize);
UNRECOVERABLE_IF(nullptr == blockForSip);
auto err = memcpy_s(blockForSip, sipSize, sip.getBinary(), sipSize);
UNRECOVERABLE_IF(err != 0);
}
// verify that SIP CSR kernel resides at the begining of the InstructionHeap
bool PreemptionHelper::isValidInstructionHeapForMidThreadPreemption(const LinearStream &ih, const Device &device) {
const SipKernel &sip = BuiltIns::getInstance().getSipKernel(SipKernelType::Csr, device);
if (ih.getUsed() < sip.getBinarySize()) {
return false;
}
return (0 == memcmp(ih.getBase(), sip.getBinary(), sip.getBinarySize()));
}
} // namespace OCLRT

View File

@ -38,11 +38,22 @@ class PreemptionHelper {
static bool allowMidThreadPreemption(Kernel *kernel, Device &device);
static void adjustDefaultPreemptionMode(RuntimeCapabilityTable &deviceCapabilities, bool allowMidThread, bool allowThreadGroup, bool allowMidBatch);
template <typename GfxFamily>
static void programCmdStream(LinearStream *cmdStream, PreemptionMode &preemptionMode, GraphicsAllocation *preemptionCsr, GraphicsAllocation *sipKernel);
static size_t getInstructionHeapSipKernelReservedSize(const Device &device);
static void initializeInstructionHeapSipKernelReservedBlock(LinearStream &ih, const Device &device);
static bool isValidInstructionHeapForMidThreadPreemption(const LinearStream &ih, const Device &device);
template <typename GfxFamily>
static size_t getRequiredCmdStreamSize(PreemptionMode preemptionMode);
static size_t getRequiredPreambleSize(const Device &device);
template <typename GfxFamily>
static void programPreamble(LinearStream &preambleCmdStream, const Device &device, const GraphicsAllocation *preemptionCsr);
template <typename GfxFamily>
static size_t getRequiredCmdStreamSize(PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode);
template <typename GfxFamily>
static void programCmdStream(LinearStream &cmdStream, PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode,
GraphicsAllocation *preemptionCsr, const LinearStream &ih, const Device &device);
template <typename GfxFamily>
static size_t getPreemptionWaCsSize(const Device &device);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -52,7 +52,7 @@ void CommandStreamReceiverHw<Family>::addDcFlushToPipeControl(Family::PIPE_CONTR
pCmd->setDcFlushEnable(flushDC);
}
template size_t getSizeRequiredPreambleCS<Family>(const HardwareInfo &hwInfo);
template size_t getSizeRequiredPreambleCS<Family>(const Device &hwInfo);
template <>
void populateFactoryTable<CommandStreamReceiverHw<Family>>() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -37,7 +37,7 @@ void PreambleHelper<BDWFamily>::programThreadArbitration(LinearStream *pCommandS
}
template <>
uint32_t PreambleHelper<BDWFamily>::getAdditionalCommandsSize(const HardwareInfo &hwInfo) {
uint32_t PreambleHelper<BDWFamily>::getAdditionalCommandsSize(const Device &device) {
return 0;
}

View File

@ -35,23 +35,42 @@ static constexpr uint32_t cmdLevelVal = (1 << 2);
}; // namespace PreemptionBDW
template <>
void PreemptionHelper::programCmdStream<GfxFamily>(LinearStream *cmdStream, PreemptionMode &preemptionMode, GraphicsAllocation *preemptionCsr, GraphicsAllocation *sipKernel) {
void PreemptionHelper::programCmdStream<GfxFamily>(LinearStream &cmdStream, PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode,
GraphicsAllocation *preemptionCsr, const LinearStream &ih, const Device &device) {
if (newPreemptionMode == oldPreemptionMode) {
return;
}
uint32_t regVal = 0;
if (preemptionMode == PreemptionMode::ThreadGroup) {
if (newPreemptionMode == PreemptionMode::ThreadGroup) {
regVal = PreemptionBDW::threadGroupVal;
} else {
regVal = PreemptionBDW::cmdLevelVal;
}
LriHelper<GfxFamily>::program(cmdStream, PreemptionBDW::mmioAddress, regVal);
LriHelper<GfxFamily>::program(&cmdStream, PreemptionBDW::mmioAddress, regVal);
}
template <>
size_t PreemptionHelper::getRequiredCmdStreamSize<GfxFamily>(PreemptionMode preemptionMode) {
size_t PreemptionHelper::getRequiredCmdStreamSize<GfxFamily>(PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode) {
if (newPreemptionMode == oldPreemptionMode) {
return 0;
}
return sizeof(typename GfxFamily::MI_LOAD_REGISTER_IMM);
}
template <>
size_t PreemptionHelper::getRequiredPreambleSize<GfxFamily>(const Device &device) {
return 0;
}
template <>
void PreemptionHelper::programPreamble<GfxFamily>(LinearStream &preambleCmdStream, const Device &device,
const GraphicsAllocation *preemptionCsr) {
}
template size_t PreemptionHelper::getPreemptionWaCsSize<GfxFamily>(const Device &device);
template void PreemptionHelper::applyPreemptionWaCmdsBegin<GfxFamily>(LinearStream *pCommandStream, const Device &device);
template void PreemptionHelper::applyPreemptionWaCmdsEnd<GfxFamily>(LinearStream *pCommandStream, const Device &device);
} // namespace OCLRT

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -56,7 +56,7 @@ template <>
void CommandStreamReceiverHw<Family>::addDcFlushToPipeControl(Family::PIPE_CONTROL *pCmd, bool flushDC) {
}
template size_t getSizeRequiredPreambleCS<Family>(const HardwareInfo &hwInfo);
template size_t getSizeRequiredPreambleCS<Family>(const Device &device);
template <>
void populateFactoryTable<CommandStreamReceiverHw<Family>>() {

View File

@ -20,6 +20,9 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <cstring>
#include "runtime/built_ins/built_ins.h"
#include "runtime/command_stream/preemption.h"
#include "runtime/command_stream/preemption.inl"
#include "runtime/memory_manager/graphics_allocation.h"
@ -40,33 +43,62 @@ static constexpr uint32_t midThreadVal = 0;
}; // namespace PreemptionSKL
template <>
void PreemptionHelper::programCmdStream<GfxFamily>(LinearStream *cmdStream, PreemptionMode &preemptionMode, GraphicsAllocation *preemptionCsr, GraphicsAllocation *sipKernel) {
void PreemptionHelper::programCmdStream<GfxFamily>(LinearStream &cmdStream,
PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode,
GraphicsAllocation *preemptionCsr,
const LinearStream &ih, const Device &device) {
if (oldPreemptionMode == newPreemptionMode) {
DEBUG_BREAK_IF((newPreemptionMode == PreemptionMode::MidThread) && (false == isValidInstructionHeapForMidThreadPreemption(ih, device)));
return;
}
uint32_t regVal = 0;
if (preemptionMode == PreemptionMode::MidThread) {
if (newPreemptionMode == PreemptionMode::MidThread) {
regVal = PreemptionSKL::midThreadVal | PreemptionSKL::mask;
} else if (preemptionMode == PreemptionMode::ThreadGroup) {
} else if (newPreemptionMode == PreemptionMode::ThreadGroup) {
regVal = PreemptionSKL::threadGroupVal | PreemptionSKL::mask;
} else {
regVal = PreemptionSKL::cmdLevelVal | PreemptionSKL::mask;
}
LriHelper<GfxFamily>::program(cmdStream, PreemptionSKL::mmioAddress, regVal);
if (preemptionMode == PreemptionMode::MidThread) {
typedef typename GfxFamily::GPGPU_CSR_BASE_ADDRESS GPGPU_CSR_BASE_ADDRESS;
auto csr = (GPGPU_CSR_BASE_ADDRESS *)cmdStream->getSpace(sizeof(GPGPU_CSR_BASE_ADDRESS));
*csr = GPGPU_CSR_BASE_ADDRESS::sInit();
csr->setGpgpuCsrBaseAddress(preemptionCsr->getGpuAddressToPatch());
}
LriHelper<GfxFamily>::program(&cmdStream, PreemptionSKL::mmioAddress, regVal);
}
template <>
size_t PreemptionHelper::getRequiredCmdStreamSize<GfxFamily>(PreemptionMode preemptionMode) {
size_t size = sizeof(typename GfxFamily::MI_LOAD_REGISTER_IMM);
if (preemptionMode == PreemptionMode::MidThread) {
size += sizeof(typename GfxFamily::GPGPU_CSR_BASE_ADDRESS);
size_t PreemptionHelper::getRequiredCmdStreamSize<GfxFamily>(PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode) {
if (newPreemptionMode == oldPreemptionMode) {
return 0;
}
return size;
return sizeof(typename GfxFamily::MI_LOAD_REGISTER_IMM);
}
template <>
size_t PreemptionHelper::getRequiredPreambleSize<GfxFamily>(const Device &device) {
if (device.getPreemptionMode() != PreemptionMode::MidThread) {
return 0;
}
return sizeof(typename GfxFamily::GPGPU_CSR_BASE_ADDRESS) + sizeof(typename GfxFamily::STATE_SIP);
}
template <>
void PreemptionHelper::programPreamble<GfxFamily>(LinearStream &preambleCmdStream, const Device &device,
const GraphicsAllocation *preemptionCsr) {
if (device.getPreemptionMode() != PreemptionMode::MidThread) {
return;
}
UNRECOVERABLE_IF(nullptr == preemptionCsr);
using GPGPU_CSR_BASE_ADDRESS = typename GfxFamily::GPGPU_CSR_BASE_ADDRESS;
using STATE_SIP = typename GfxFamily::STATE_SIP;
auto csr = reinterpret_cast<GPGPU_CSR_BASE_ADDRESS *>(preambleCmdStream.getSpace(sizeof(GPGPU_CSR_BASE_ADDRESS)));
csr->init();
csr->setGpgpuCsrBaseAddress(preemptionCsr->getGpuAddressToPatch());
auto sip = reinterpret_cast<STATE_SIP *>(preambleCmdStream.getSpace(sizeof(STATE_SIP)));
sip->init();
sip->setSystemInstructionPointer(0);
}
template size_t PreemptionHelper::getPreemptionWaCsSize<GfxFamily>(const Device &device);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -28,6 +28,7 @@ namespace OCLRT {
struct HardwareInfo;
class Device;
class GraphicsAllocation;
class LinearStream;
template <typename GfxFamily>
@ -37,13 +38,15 @@ struct PreambleHelper {
static void programL3(LinearStream *pCommandStream, uint32_t l3Config);
static void programPipelineSelect(LinearStream *pCommandStream);
static void programThreadArbitration(LinearStream *pCommandStream, uint32_t requiredThreadArbitrationPolicy);
static void programPreemption(LinearStream *pCommandStream, const Device &device, GraphicsAllocation *preemptionCsr);
static void setupPipeControlInFrontOfCommand(void *pCmd, const HardwareInfo *hwInfo, bool isVfeCommand);
static void programVFEState(LinearStream *pCommandStream, const HardwareInfo &hwInfo, int scratchSize, uint64_t scratchAddress);
static void programPreamble(LinearStream *pCommandStream, const HardwareInfo &hwInfo, uint32_t l3Config, uint32_t requiredThreadArbitrationPolicy);
static void programPreamble(LinearStream *pCommandStream, const Device &device, uint32_t l3Config,
uint32_t requiredThreadArbitrationPolicy, GraphicsAllocation *preemptionCsr);
static uint32_t getL3Config(const HardwareInfo &hwInfo, bool useSLM);
static void programPSForMedia(LinearStream *pCommandStream, bool enable);
static bool getMediaSamplerDopClockGateEnable(LinearStream *pCommandStream);
static uint32_t getAdditionalCommandsSize(const HardwareInfo &hwInfo);
static uint32_t getAdditionalCommandsSize(const Device &device);
static void programGenSpecificPreambleWorkArounds(LinearStream *pCommandStream, const HardwareInfo &hwInfo);
static uint32_t getUrbEntryAllocationSize();
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -22,6 +22,7 @@
#include "runtime/helpers/preamble.h"
#include "runtime/command_stream/linear_stream.h"
#include "runtime/command_stream/preemption.h"
#include "hw_cmds.h"
#include "reg_configs.h"
#include "runtime/device/device.h"
@ -64,10 +65,12 @@ void PreambleHelper<GfxFamily>::programGenSpecificPreambleWorkArounds(LinearStre
}
template <typename GfxFamily>
uint32_t PreambleHelper<GfxFamily>::getAdditionalCommandsSize(const HardwareInfo &hwInfo) {
uint32_t PreambleHelper<GfxFamily>::getAdditionalCommandsSize(const Device &device) {
typedef typename GfxFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
typedef typename GfxFamily::PIPE_CONTROL PIPE_CONTROL;
return sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL);
size_t requiredSize = sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL);
requiredSize += PreemptionHelper::getRequiredPreambleSize<GfxFamily>(device);
return static_cast<uint32_t>(requiredSize);
}
template <typename GfxFamily>
@ -105,11 +108,18 @@ void PreambleHelper<GfxFamily>::programL3(LinearStream *pCommandStream, uint32_t
}
template <typename GfxFamily>
void PreambleHelper<GfxFamily>::programPreamble(LinearStream *pCommandStream, const HardwareInfo &hwInfo, uint32_t l3Config, uint32_t requiredThreadArbitrationPolicy) {
void PreambleHelper<GfxFamily>::programPreamble(LinearStream *pCommandStream, const Device &device, uint32_t l3Config,
uint32_t requiredThreadArbitrationPolicy, GraphicsAllocation *preemptionCsr) {
programL3(pCommandStream, l3Config);
programPipelineSelect(pCommandStream);
programThreadArbitration(pCommandStream, requiredThreadArbitrationPolicy);
programGenSpecificPreambleWorkArounds(pCommandStream, hwInfo);
programPreemption(pCommandStream, device, preemptionCsr);
programGenSpecificPreambleWorkArounds(pCommandStream, device.getHardwareInfo());
}
template <typename GfxFamily>
void PreambleHelper<GfxFamily>::programPreemption(LinearStream *pCommandStream, const Device &device, GraphicsAllocation *preemptionCsr) {
PreemptionHelper::programPreamble<GfxFamily>(*pCommandStream, device, preemptionCsr);
}
template <typename GfxFamily>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -36,8 +36,10 @@
#include "unit_tests/fixtures/memory_management_fixture.h"
#include "unit_tests/helpers/debug_manager_state_restore.h"
#include "unit_tests/libult/ult_command_stream_receiver.h"
#include "unit_tests/mocks/mock_memory_manager.h"
#include "unit_tests/mocks/mock_command_queue.h"
#include "unit_tests/mocks/mock_context.h"
#include "unit_tests/mocks/mock_csr.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
@ -741,3 +743,26 @@ HWTEST_F(KmdNotifyTests, givenMultipleCommandQueuesWhenMarkerIsEmittedThenGraphi
auto commandStreamGraphicsAllocation2 = commandQ->getCS(0).getGraphicsAllocation();
EXPECT_EQ(commandStreamGraphicsAllocation, commandStreamGraphicsAllocation2);
}
TEST(CommandQueueGetIndirectHeap, whenNewInstructionHeapIsBeingCreatedThenCommandStreamReceiverCanReserveAMemoryBlockAtItsBegining) {
char pattern[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39, 41};
static_assert(false == isAligned<MemoryConstants::cacheLineSize>(sizeof(pattern)),
"Will be checking for automatic cacheline alignment, so pattern length must not be a multiple of cacheline");
size_t alignedPatternSize = alignUp(sizeof(pattern), MemoryConstants::cacheLineSize);
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
MockCommandStreamReceiver *csr = new MockCommandStreamReceiver;
mockDevice->resetCommandStreamReceiver(csr);
csr->instructionHeapReserveredData.assign(pattern, pattern + sizeof(pattern));
MockCommandQueue cmdQ{nullptr, mockDevice.get(), nullptr};
IndirectHeap &heap = cmdQ.getIndirectHeap(OCLRT::IndirectHeap::INSTRUCTION, 8192);
EXPECT_LE(8192U, heap.getAvailableSpace());
EXPECT_EQ(alignedPatternSize, heap.getUsed());
ASSERT_LE(sizeof(pattern), heap.getMaxAvailableSpace());
char *reservedBlock = reinterpret_cast<char *>(heap.getBase());
auto dataFoundInReservedBlock = ArrayRef<char>(reservedBlock, sizeof(pattern));
auto expectedData = ArrayRef<char>(csr->instructionHeapReserveredData);
EXPECT_THAT(dataFoundInReservedBlock, testing::ContainerEq(expectedData));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -565,7 +565,7 @@ HWTEST_F(CommandStreamReceiverFlushTaskTests, flushTaskWithOnlyEnoughMemoryForPr
commandStreamReceiver.lastSentL3Config = l3Config;
auto &csrCS = commandStreamReceiver.getCS();
size_t sizeNeededForPreamble = getSizeRequiredPreambleCS<FamilyType>(commandStreamReceiver.hwInfo);
size_t sizeNeededForPreamble = getSizeRequiredPreambleCS<FamilyType>(MockDevice(commandStreamReceiver.hwInfo));
size_t sizeNeededForStateBaseAddress = sizeof(STATE_BASE_ADDRESS) + sizeof(PIPE_CONTROL);
size_t sizeNeededForPipeControl = commandStreamReceiver.getRequiredPipeControlSize();
size_t sizeNeeded = sizeNeededForPreamble +
@ -598,7 +598,7 @@ HWTEST_F(CommandStreamReceiverFlushTaskTests, flushTaskWithOnlyEnoughMemoryForPr
commandStreamReceiver.lastSentL3Config = l3Config;
auto &csrCS = commandStreamReceiver.getCS();
size_t sizeNeededForPreamble = getSizeRequiredPreambleCS<FamilyType>(commandStreamReceiver.hwInfo);
size_t sizeNeededForPreamble = getSizeRequiredPreambleCS<FamilyType>(MockDevice(commandStreamReceiver.hwInfo));
size_t sizeNeededForStateBaseAddress = sizeof(STATE_BASE_ADDRESS) + sizeof(PIPE_CONTROL);
size_t sizeNeededForPipeControl = commandStreamReceiver.getRequiredPipeControlSize();
size_t sizeNeeded = sizeNeededForPreamble +
@ -631,7 +631,7 @@ HWTEST_F(CommandStreamReceiverFlushTaskTests, flushTaskWithOnlyEnoughMemoryForPr
commandStreamReceiver.lastSentL3Config = l3Config;
auto &csrCS = commandStreamReceiver.getCS();
size_t sizeNeeded = getSizeRequiredPreambleCS<FamilyType>(commandStreamReceiver.hwInfo) +
size_t sizeNeeded = getSizeRequiredPreambleCS<FamilyType>(MockDevice(commandStreamReceiver.hwInfo)) +
sizeof(STATE_BASE_ADDRESS) +
sizeof(PIPE_CONTROL) +
commandStreamReceiver.getRequiredPipeControlSize() +
@ -639,7 +639,8 @@ HWTEST_F(CommandStreamReceiverFlushTaskTests, flushTaskWithOnlyEnoughMemoryForPr
sizeNeeded = alignUp(sizeNeeded, MemoryConstants::cacheLineSize);
csrCS.getSpace(csrCS.getAvailableSpace() - commandStreamReceiver.getRequiredCsrSize());
DispatchFlags flags;
csrCS.getSpace(csrCS.getAvailableSpace() - commandStreamReceiver.getRequiredCmdStreamSize(flags));
auto expectedBase = csrCS.getBase();
// This case handles when we have *just* enough space
@ -1784,11 +1785,12 @@ HWTEST_F(CommandStreamReceiverFlushTaskTests, requiredCsrSizeAlignedToCacheline)
csrSizeRequest.l3ConfigChanged = true;
commandStreamReceiver.overrideCsrSizeReqFlags(csrSizeRequest);
auto l3ConfigChangedSize = commandStreamReceiver.getRequiredCsrSize();
DispatchFlags flags;
auto l3ConfigChangedSize = commandStreamReceiver.getRequiredCmdStreamSize(flags);
csrSizeRequest.l3ConfigChanged = false;
commandStreamReceiver.overrideCsrSizeReqFlags(csrSizeRequest);
auto l3ConfigNotChangedSize = commandStreamReceiver.getRequiredCsrSize();
auto l3ConfigNotChangedSize = commandStreamReceiver.getRequiredCmdStreamSize(flags);
EXPECT_EQ(alignUp(l3ConfigChangedSize, MemoryConstants::cacheLineSize), l3ConfigChangedSize);
EXPECT_EQ(alignUp(l3ConfigNotChangedSize, MemoryConstants::cacheLineSize), l3ConfigNotChangedSize);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
#include "runtime/command_stream/linear_stream.h"
#include "runtime/command_stream/command_stream_receiver.h"
#include "runtime/command_stream/thread_arbitration_policy.h"
#include "runtime/command_stream/preemption.h"
#include "runtime/memory_manager/memory_manager.h"
#include "runtime/memory_manager/graphics_allocation.h"
#include "runtime/mem_obj/buffer.h"
@ -30,10 +31,13 @@
#include "unit_tests/mocks/mock_context.h"
#include "unit_tests/fixtures/device_fixture.h"
#include "unit_tests/fixtures/memory_management_fixture.h"
#include "unit_tests/mocks/mock_builtins.h"
#include "unit_tests/mocks/mock_csr.h"
#include "test.h"
#include "runtime/helpers/cache_policy.h"
#include "gmock/gmock-matchers.h"
using namespace OCLRT;
struct CommandStreamReceiverTest : public DeviceFixture,
@ -204,3 +208,39 @@ HWTEST_F(CommandStreamReceiverTest, givenDefaultCommandStreamReceiverThenDefault
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();
EXPECT_EQ(CommandStreamReceiver::DispatchMode::ImmediateDispatch, csr.dispatchMode);
}
TEST(CommandStreamReceiver, cmdStreamReceiverReservedBlockInInstructionHeapIsBasedOnPreemptionHelper) {
char pattern[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39, 41};
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
{
MockBuiltins mockBuiltins;
mockBuiltins.overrideGlobalBuiltins();
{
auto sipOverride = std::unique_ptr<OCLRT::SipKernel>(new OCLRT::SipKernel(OCLRT::SipKernelType::Csr,
pattern, sizeof(pattern)));
mockBuiltins.overrideSipKernel(std::move(sipOverride));
}
size_t reservedSize = mockDevice->getCommandStreamReceiver().getInstructionHeapCmdStreamReceiverReservedSize();
size_t expectedSize = OCLRT::PreemptionHelper::getInstructionHeapSipKernelReservedSize(*mockDevice);
EXPECT_NE(0U, expectedSize);
EXPECT_EQ(expectedSize, reservedSize);
ASSERT_LE(expectedSize, reservedSize);
StackVec<char, 4096> cmdStreamIhBuffer;
cmdStreamIhBuffer.resize(reservedSize);
LinearStream cmdStreamReceiverInstrucionHeap{cmdStreamIhBuffer.begin(), cmdStreamIhBuffer.size()};
mockDevice->getCommandStreamReceiver().initializeInstructionHeapCmdStreamReceiverReservedBlock(cmdStreamReceiverInstrucionHeap);
StackVec<char, 4096> preemptionHelperIhBuffer;
preemptionHelperIhBuffer.resize(expectedSize);
LinearStream preemptionHelperInstrucionHeap{preemptionHelperIhBuffer.begin(), preemptionHelperIhBuffer.size()};
PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(preemptionHelperInstrucionHeap, *mockDevice);
cmdStreamIhBuffer.resize(expectedSize);
EXPECT_THAT(preemptionHelperIhBuffer, testing::ContainerEq(cmdStreamIhBuffer));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -71,7 +71,10 @@ BDWTEST_F(ThreadArbitrationGen8, givenPreambleWhenItIsProgrammedThenThreadArbitr
typedef BDWFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
LinearStream &cs = linearStream;
uint32_t l3Config = PreambleHelper<BDWFamily>::getL3Config(**platformDevices, true);
PreambleHelper<BDWFamily>::programPreamble(&linearStream, **platformDevices, l3Config, ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin);
PreambleHelper<BDWFamily>::programPreamble(&linearStream, MockDevice(**platformDevices), l3Config,
ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin,
nullptr);
parseCommands<BDWFamily>(cs);
@ -84,7 +87,7 @@ BDWTEST_F(ThreadArbitrationGen8, givenPreambleWhenItIsProgrammedThenThreadArbitr
EXPECT_EQ(RegisterOffset, lri.getRegisterOffset());
EXPECT_EQ(1u, lri.getDataDword() & 1);
EXPECT_EQ(0u, PreambleHelper<BDWFamily>::getAdditionalCommandsSize(**platformDevices));
EXPECT_EQ(0u, PreambleHelper<BDWFamily>::getAdditionalCommandsSize(MockDevice(**platformDevices)));
}
typedef PreambleFixture Gen8UrbEntryAllocationSize;

View File

@ -50,6 +50,15 @@ GEN8TEST_F(Gen8PreemptionTests, allowThreadGroupPreemptionReturnsTrue) {
EXPECT_TRUE(PreemptionHelper::allowThreadGroupPreemption(kernel.get(), waTable));
}
GEN8TEST_F(Gen8PreemptionTests, doesNotProgramPreamble) {
size_t requiredSize = PreemptionHelper::getRequiredPreambleSize<FamilyType>(*device);
EXPECT_EQ(0U, requiredSize);
LinearStream cmdStream{nullptr, 0};
PreemptionHelper::programPreamble<FamilyType>(cmdStream, *device, nullptr);
EXPECT_EQ(0U, cmdStream.getUsed());
}
GEN8TEST_F(Gen8PreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogram) {
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
auto &csr = pDevice->getUltCommandStreamReceiver<FamilyType>();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -21,10 +21,11 @@
*/
#include "runtime/command_stream/thread_arbitration_policy.h"
#include "runtime/command_stream/preemption.h"
#include "runtime/gen9/reg_configs.h"
#include "runtime/helpers/preamble.h"
#include "unit_tests/preamble/preamble_fixture.h"
#include "unit_tests/gen_common/gen_cmd_parse.h"
#include "runtime/gen9/reg_configs.h"
using namespace OCLRT;
@ -76,10 +77,11 @@ typedef PreambleFixture ThreadArbitration;
SKLTEST_F(ThreadArbitration, givenPreambleWhenItIsProgrammedThenThreadArbitrationIsSetToRoundRobin) {
typedef SKLFamily::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM;
typedef SKLFamily::PIPE_CONTROL PIPE_CONTROL;
HardwareInfo hwInfo;
LinearStream &cs = linearStream;
uint32_t l3Config = PreambleHelper<FamilyType>::getL3Config(**platformDevices, true);
PreambleHelper<SKLFamily>::programPreamble(&linearStream, **platformDevices, l3Config, ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin);
PreambleHelper<SKLFamily>::programPreamble(&linearStream, MockDevice(**platformDevices), l3Config,
ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin,
nullptr);
parseCommands<SKLFamily>(cs);
@ -93,7 +95,8 @@ SKLTEST_F(ThreadArbitration, givenPreambleWhenItIsProgrammedThenThreadArbitratio
EXPECT_EQ(0xE404u, lri.getRegisterOffset());
EXPECT_EQ(0x100u, lri.getDataDword());
EXPECT_EQ(sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL), PreambleHelper<SKLFamily>::getAdditionalCommandsSize(hwInfo));
EXPECT_EQ(sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL),
PreambleHelper<SKLFamily>::getAdditionalCommandsSize(MockDevice(*platformDevices[0])));
}
GEN9TEST_F(PreambleVfeState, WaOff) {

View File

@ -60,6 +60,50 @@ PreemptionTestHwDetails GetPreemptionTestHwDetails<SKLFamily>() {
return ret;
}
GEN9TEST_F(Gen9PreemptionTests, whenMidThreadPreemptionIsNotAvailableThenDoesNotProgramPreamble) {
device->setPreemptionMode(PreemptionMode::ThreadGroup);
size_t requiredSize = PreemptionHelper::getRequiredPreambleSize<FamilyType>(*device);
EXPECT_EQ(0U, requiredSize);
LinearStream cmdStream{nullptr, 0};
PreemptionHelper::programPreamble<FamilyType>(cmdStream, *device, nullptr);
EXPECT_EQ(0U, cmdStream.getUsed());
}
GEN9TEST_F(Gen9PreemptionTests, whenMidThreadPreemptionIsAvailableThenProgramsPreamble) {
using GPGPU_CSR_BASE_ADDRESS = typename FamilyType::GPGPU_CSR_BASE_ADDRESS;
using STATE_SIP = typename FamilyType::STATE_SIP;
device->setPreemptionMode(PreemptionMode::MidThread);
executionEnvironment->DisableMidThreadPreemption = 0;
size_t minCsrSize = device->getHardwareInfo().pSysInfo->CsrSizeInMb * MemoryConstants::megaByte;
uint64_t minCsrAlignment = 2 * 256 * MemoryConstants::kiloByte;
MockGraphicsAllocation csrSurface((void *)minCsrAlignment, minCsrSize);
// verify preamble programming
size_t requiredPreambleSize = PreemptionHelper::getRequiredPreambleSize<FamilyType>(*device);
size_t expectedPreambleSize = sizeof(GPGPU_CSR_BASE_ADDRESS) + sizeof(STATE_SIP);
EXPECT_EQ(expectedPreambleSize, requiredPreambleSize);
StackVec<char, 8192> preambleStorage(requiredPreambleSize);
ASSERT_LE(requiredPreambleSize, preambleStorage.size());
LinearStream preambleCmdStream{preambleStorage.begin(), preambleStorage.size()};
PreemptionHelper::programPreamble<FamilyType>(preambleCmdStream, *device, &csrSurface);
HardwareParse hwParsePreamble;
hwParsePreamble.parseCommands<FamilyType>(preambleCmdStream);
auto csrBaseAddressCmd = hwParsePreamble.getCommand<GPGPU_CSR_BASE_ADDRESS>();
ASSERT_NE(nullptr, csrBaseAddressCmd);
EXPECT_EQ(csrSurface.getGpuAddressToPatch(), csrBaseAddressCmd->getGpgpuCsrBaseAddress());
auto stateSipCmd = hwParsePreamble.getCommand<STATE_SIP>();
ASSERT_NE(nullptr, stateSipCmd);
EXPECT_EQ(0U, stateSipCmd->getSystemInstructionPointer());
}
GEN9TEST_F(Gen9ThreadGroupPreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogramThreadGroupNoWa) {
pDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
WhitelistedRegisters regs = {};

View File

@ -1,4 +1,4 @@
# Copyright (c) 2017, Intel Corporation
# Copyright (c) 2018, Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@ -24,6 +24,7 @@ set(IGDRCL_SRCS_tests_mocks
"${CMAKE_CURRENT_SOURCE_DIR}/mock_async_event_handler.h"
"${CMAKE_CURRENT_SOURCE_DIR}/mock_block_kernel_manager.h"
"${CMAKE_CURRENT_SOURCE_DIR}/mock_buffer.h"
"${CMAKE_CURRENT_SOURCE_DIR}/mock_builtins.h"
"${CMAKE_CURRENT_SOURCE_DIR}/mock_cif.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/mock_cif.h"
"${CMAKE_CURRENT_SOURCE_DIR}/mock_command_queue.h"

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "runtime/built_ins/built_ins.h"
#include "runtime/built_ins/sip.h"
#include <memory>
class MockBuiltins : public OCLRT::BuiltIns {
public:
MockBuiltins() {
originalGlobalBuiltins = this;
}
~MockBuiltins() override {
if (originalGlobalBuiltins != this) {
BuiltIns::pInstance = originalGlobalBuiltins;
}
}
void overrideGlobalBuiltins() {
originalGlobalBuiltins = BuiltIns::pInstance;
BuiltIns::pInstance = this;
}
const OCLRT::SipKernel &getSipKernel(OCLRT::SipKernelType type, const OCLRT::Device &device) override {
if (sipKernelsOverride.find(type) != sipKernelsOverride.end()) {
return *sipKernelsOverride[type];
}
return BuiltIns::getSipKernel(type, device);
}
void overrideSipKernel(std::unique_ptr<OCLRT::SipKernel> kernel) {
sipKernelsOverride[kernel->getType()] = std::move(kernel);
}
OCLRT::BuiltIns *originalGlobalBuiltins = nullptr;
std::map<OCLRT::SipKernelType, std::unique_ptr<OCLRT::SipKernel>> sipKernelsOverride;
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
#include "runtime/memory_manager/graphics_allocation.h"
#include "runtime/helpers/options.h"
#include "runtime/helpers/flush_stamp.h"
#include "runtime/helpers/string.h"
#include "unit_tests/libult/ult_command_stream_receiver.h"
#include <vector>
@ -198,6 +199,10 @@ class MockCommandStreamReceiver : public CommandStreamReceiver {
public:
using CommandStreamReceiver::latestSentTaskCount;
using CommandStreamReceiver::tagAddress;
std::vector<char> instructionHeapReserveredData;
~MockCommandStreamReceiver() {
}
FlushStamp flush(BatchBuffer &batchBuffer, EngineType engineOrdinal, ResidencyContainer *allocationsForResidency) override;
@ -221,4 +226,23 @@ class MockCommandStreamReceiver : public CommandStreamReceiver {
}
void setOSInterface(OSInterface *osInterface);
size_t getInstructionHeapCmdStreamReceiverReservedSize() const override {
if (instructionHeapReserveredData.size() == 0) {
return CommandStreamReceiver::getInstructionHeapCmdStreamReceiverReservedSize();
}
return instructionHeapReserveredData.size();
}
void initializeInstructionHeapCmdStreamReceiverReservedBlock(LinearStream &ih) const override {
if (instructionHeapReserveredData.size() == 0) {
CommandStreamReceiver::initializeInstructionHeapCmdStreamReceiverReservedBlock(ih);
return;
}
void *block = ih.getSpace(instructionHeapReserveredData.size());
memcpy_s(block, instructionHeapReserveredData.size(),
instructionHeapReserveredData.data(), instructionHeapReserveredData.size());
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -40,6 +40,7 @@ extern bool initialized;
class MockDevice : public Device {
public:
using Device::initializeCaps;
using Device::commandStreamReceiver;
void setOSTime(OSTime *osTime);
void setDriverInfo(DriverInfo *driverInfo);

View File

@ -1,4 +1,4 @@
# Copyright (c) 2017, Intel Corporation
# Copyright (c) 2018, Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@ -22,4 +22,5 @@ set(IGDRCL_SRCS_tests_preamble
"${IGDRCL_SRCS_tests_preamble}"
"${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt"
"${CMAKE_CURRENT_SOURCE_DIR}/preamble_fixture.h"
"${CMAKE_CURRENT_SOURCE_DIR}/preamble_tests.cpp"
PARENT_SCOPE)

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "runtime/command_stream/preemption.h"
#include "runtime/helpers/preamble.h"
#include "runtime/utilities/stackvec.h"
#include "unit_tests/gen_common/test.h"
#include "unit_tests/mocks/mock_device.h"
#include "unit_tests/mocks/mock_graphics_allocation.h"
#include <gtest/gtest.h>
#include <algorithm>
using PreambleTest = ::testing::Test;
using namespace OCLRT;
HWTEST_F(PreambleTest, PreemptionIsTakenIntoAccountWhenProgrammingPreamble) {
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
uint32_t cmdSizePreambleMidThread = PreambleHelper<FamilyType>::getAdditionalCommandsSize(*mockDevice);
uint32_t cmdSizePreemptionMidThread = static_cast<uint32_t>(PreemptionHelper::getRequiredPreambleSize<FamilyType>(*mockDevice));
mockDevice->setPreemptionMode(PreemptionMode::Disabled);
uint32_t cmdSizePreambleDisabled = PreambleHelper<FamilyType>::getAdditionalCommandsSize(*mockDevice);
uint32_t cmdSizePreemptionDisabled = static_cast<uint32_t>(PreemptionHelper::getRequiredPreambleSize<FamilyType>(*mockDevice));
EXPECT_LE(cmdSizePreemptionMidThread, cmdSizePreambleMidThread);
EXPECT_LE(cmdSizePreemptionDisabled, cmdSizePreambleDisabled);
EXPECT_LE(cmdSizePreemptionDisabled, cmdSizePreemptionMidThread);
EXPECT_LE((cmdSizePreemptionMidThread - cmdSizePreemptionDisabled), (cmdSizePreambleMidThread - cmdSizePreambleDisabled));
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
StackVec<char, 8192> preambleBuffer(8192);
LinearStream preambleStream(&*preambleBuffer.begin(), preambleBuffer.size());
StackVec<char, 4096> preemptionBuffer;
preemptionBuffer.resize(cmdSizePreemptionMidThread);
LinearStream preemptionStream(&*preemptionBuffer.begin(), preemptionBuffer.size());
uintptr_t minCsrAlignment = 2 * 256 * MemoryConstants::kiloByte;
MockGraphicsAllocation csrSurface(reinterpret_cast<void *>(minCsrAlignment), 1024);
PreambleHelper<FamilyType>::programPreamble(&preambleStream, *mockDevice, 0U,
ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin, &csrSurface);
PreemptionHelper::programPreamble<FamilyType>(preemptionStream, *mockDevice, &csrSurface);
ASSERT_LE(preemptionStream.getUsed(), preambleStream.getUsed());
auto it = std::search(&preambleBuffer[0], &preambleBuffer[preambleStream.getUsed()],
&preemptionBuffer[0], &preemptionBuffer[preemptionStream.getUsed()]);
EXPECT_NE(&preambleBuffer[preambleStream.getUsed()], it);
}

View File

@ -25,6 +25,7 @@
#include "unit_tests/fixtures/preemption_fixture.h"
#include "unit_tests/helpers/debug_manager_state_restore.h"
#include "unit_tests/helpers/hw_parse.h"
#include "unit_tests/mocks/mock_builtins.h"
#include "unit_tests/mocks/mock_device.h"
#include "unit_tests/mocks/mock_graphics_allocation.h"
#include "unit_tests/mocks/mock_kernel.h"
@ -288,21 +289,157 @@ TEST(PreemptionTest, defaultMode) {
EXPECT_EQ(0, DebugManager.flags.ForcePreemptionMode.get());
}
TEST(PreemptionTest, whenPreemptionModeIsNotMidThreadThenInstructionHeapSipKernelReservedSizeIsEmpty) {
char buffer[4096];
LinearStream instructionHeap(buffer, sizeof(buffer));
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
mockDevice->setPreemptionMode(PreemptionMode::Disabled);
EXPECT_EQ(0U, PreemptionHelper::getInstructionHeapSipKernelReservedSize(*mockDevice));
PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(instructionHeap, *mockDevice);
ASSERT_EQ(0U, instructionHeap.getUsed());
mockDevice->setPreemptionMode(PreemptionMode::MidBatch);
EXPECT_EQ(0U, PreemptionHelper::getInstructionHeapSipKernelReservedSize(*mockDevice));
PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(instructionHeap, *mockDevice);
ASSERT_EQ(0U, instructionHeap.getUsed());
mockDevice->setPreemptionMode(PreemptionMode::ThreadGroup);
EXPECT_EQ(0U, PreemptionHelper::getInstructionHeapSipKernelReservedSize(*mockDevice));
PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(instructionHeap, *mockDevice);
ASSERT_EQ(0U, instructionHeap.getUsed());
}
TEST(PreemptionTest, instructionHeapIsInvalidIfItSmallerThanSipKernel) {
char instructionHeapBuffer[4096];
LinearStream instructionHeap(instructionHeapBuffer, sizeof(instructionHeapBuffer));
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
char sipPattern[] = {2, 3, 5, 11, 13, 17, 19, 23, 29, 31, 37, 39, 41};
instructionHeap.getSpace(sizeof(sipPattern) - 1);
memcpy_s(instructionHeapBuffer, sizeof(instructionHeapBuffer), sipPattern, sizeof(sipPattern));
{
MockBuiltins mockBuiltins;
mockBuiltins.overrideGlobalBuiltins();
{
auto sipOverride = std::unique_ptr<OCLRT::SipKernel>(new OCLRT::SipKernel(OCLRT::SipKernelType::Csr,
sipPattern, sizeof(sipPattern)));
mockBuiltins.overrideSipKernel(std::move(sipOverride));
}
EXPECT_FALSE(PreemptionHelper::isValidInstructionHeapForMidThreadPreemption(instructionHeap, *mockDevice));
}
}
TEST(PreemptionTest, instructionHeapIsInvalidIfItDoesNotContainSipKernelAtTheBegining) {
char instructionHeapBuffer[4096];
LinearStream instructionHeap(instructionHeapBuffer, sizeof(instructionHeapBuffer));
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
char sipPattern[] = {2, 3, 5, 11, 13, 17, 19, 23, 29, 31, 37, 39, 41};
instructionHeap.getSpace(sizeof(instructionHeapBuffer));
memcpy_s(instructionHeapBuffer + 1, sizeof(instructionHeapBuffer) - 1, sipPattern, sizeof(sipPattern));
{
MockBuiltins mockBuiltins;
mockBuiltins.overrideGlobalBuiltins();
{
auto sipOverride = std::unique_ptr<OCLRT::SipKernel>(new OCLRT::SipKernel(OCLRT::SipKernelType::Csr,
sipPattern, sizeof(sipPattern)));
mockBuiltins.overrideSipKernel(std::move(sipOverride));
}
EXPECT_FALSE(PreemptionHelper::isValidInstructionHeapForMidThreadPreemption(instructionHeap, *mockDevice));
}
}
TEST(PreemptionTest, instructionHeapIsValidIfItContainSipKernelAtTheBegining) {
char instructionHeapBuffer[4096];
LinearStream instructionHeap(instructionHeapBuffer, sizeof(instructionHeapBuffer));
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
char sipPattern[] = {2, 3, 5, 11, 13, 17, 19, 23, 29, 31, 37, 39, 41};
instructionHeap.getSpace(sizeof(instructionHeapBuffer));
memcpy_s(instructionHeapBuffer, sizeof(instructionHeapBuffer), sipPattern, sizeof(sipPattern));
{
MockBuiltins mockBuiltins;
mockBuiltins.overrideGlobalBuiltins();
{
auto sipOverride = std::unique_ptr<OCLRT::SipKernel>(new OCLRT::SipKernel(OCLRT::SipKernelType::Csr,
sipPattern, sizeof(sipPattern)));
mockBuiltins.overrideSipKernel(std::move(sipOverride));
}
EXPECT_TRUE(PreemptionHelper::isValidInstructionHeapForMidThreadPreemption(instructionHeap, *mockDevice));
}
}
TEST(PreemptionTest, whenPreemptionModeIsMidThreadThenInstructionHeapSipKernelReservedBlockIsProperlyInitialized) {
char instructionHeapBuffer[4096];
memset(instructionHeapBuffer, 7, sizeof(instructionHeapBuffer));
LinearStream instructionHeap(instructionHeapBuffer, sizeof(instructionHeapBuffer));
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
mockDevice->setPreemptionMode(PreemptionMode::MidThread);
char sipPattern[] = {2, 3, 5, 11, 13, 17, 19, 23, 29, 31, 37, 39, 41};
{
MockBuiltins mockBuiltins;
mockBuiltins.overrideGlobalBuiltins();
{
auto sipOverride = std::unique_ptr<OCLRT::SipKernel>(new OCLRT::SipKernel(OCLRT::SipKernelType::Csr,
sipPattern, sizeof(sipPattern)));
mockBuiltins.overrideSipKernel(std::move(sipOverride));
}
EXPECT_EQ(sizeof(sipPattern), PreemptionHelper::getInstructionHeapSipKernelReservedSize(*mockDevice));
PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(instructionHeap, *mockDevice);
EXPECT_TRUE(PreemptionHelper::isValidInstructionHeapForMidThreadPreemption(instructionHeap, *mockDevice));
EXPECT_EQ(7, instructionHeapBuffer[sizeof(sipPattern)]); // check for overflow
}
}
struct PreemptionHwTest : ::testing::Test, ::testing::WithParamInterface<PreemptionMode> {
};
HWTEST_P(PreemptionHwTest, getRequiredCmdStreamSizeReturns0WhenPreemptionModeIsNotChanging) {
PreemptionMode mode = GetParam();
size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize<FamilyType>(mode, mode);
EXPECT_EQ(0U, requiredSize);
StackVec<char, 4096> buffer(requiredSize);
LinearStream cmdStream(buffer.begin(), buffer.size());
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
{
MockBuiltins tmpBuiltins;
char sipData[16] = {0};
tmpBuiltins.overrideSipKernel(std::unique_ptr<OCLRT::SipKernel>(new OCLRT::SipKernel{SipKernelType::Csr, sipData, sizeof(sipData)}));
tmpBuiltins.overrideGlobalBuiltins();
PreemptionHelper::programCmdStream<FamilyType>(cmdStream, mode, mode,
nullptr, LinearStream(nullptr, 0), *mockDevice);
}
EXPECT_EQ(0U, cmdStream.getUsed());
}
HWTEST_P(PreemptionHwTest, getRequiredCmdStreamSizeReturnsSizeOfMiLoadRegisterImmWhenPreemptionModeIsChanging) {
PreemptionMode mode = GetParam();
PreemptionMode differentPreemptionMode = static_cast<PreemptionMode>(0);
if (false == GetPreemptionTestHwDetails<FamilyType>().supportsPreemptionProgramming()) {
EXPECT_EQ(0U, PreemptionHelper::getRequiredCmdStreamSize<FamilyType>(mode));
EXPECT_EQ(0U, PreemptionHelper::getRequiredCmdStreamSize<FamilyType>(mode, differentPreemptionMode));
return;
}
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize<FamilyType>(mode);
EXPECT_LE(sizeof(MI_LOAD_REGISTER_IMM), requiredSize);
size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize<FamilyType>(mode, differentPreemptionMode);
EXPECT_EQ(sizeof(MI_LOAD_REGISTER_IMM), requiredSize);
StackVec<char, 4096> buffer(requiredSize);
LinearStream cmdStream(buffer.begin(), buffer.size());
@ -313,16 +450,21 @@ HWTEST_P(PreemptionHwTest, getRequiredCmdStreamSizeReturnsSizeOfMiLoadRegisterIm
uint64_t minCsrAlignment = 2 * 256 * MemoryConstants::kiloByte;
MockGraphicsAllocation csrSurface((void *)minCsrAlignment, minCsrSize);
PreemptionHelper::programCmdStream<FamilyType>(&cmdStream, mode, &csrSurface, nullptr);
PreemptionHelper::programCmdStream<FamilyType>(cmdStream, mode, differentPreemptionMode,
nullptr, LinearStream(nullptr, 0), *mockDevice);
EXPECT_EQ(requiredSize, cmdStream.getUsed());
}
HWTEST_P(PreemptionHwTest, programCmdStreamAddsProperMiLoadRegisterImmCommandToTheStream) {
PreemptionMode mode = GetParam();
PreemptionMode differentPreemptionMode = static_cast<PreemptionMode>(0);
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
if (false == GetPreemptionTestHwDetails<FamilyType>().supportsPreemptionProgramming()) {
LinearStream cmdStream(nullptr, 0U);
PreemptionHelper::programCmdStream<FamilyType>(&cmdStream, mode, nullptr, nullptr);
LinearStream instructionHeap(nullptr, 0U);
PreemptionHelper::programCmdStream<FamilyType>(cmdStream, mode, differentPreemptionMode, nullptr,
instructionHeap, *mockDevice);
EXPECT_EQ(0U, cmdStream.getUsed());
return;
}
@ -337,17 +479,16 @@ HWTEST_P(PreemptionHwTest, programCmdStreamAddsProperMiLoadRegisterImmCommandToT
expectedRegValue = hwDetails.modeToRegValueMap[mode];
}
size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize<FamilyType>(mode);
size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize<FamilyType>(mode, differentPreemptionMode);
StackVec<char, 4096> buffer(requiredSize);
LinearStream cmdStream(buffer.begin(), buffer.size());
auto mockDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(nullptr));
size_t minCsrSize = mockDevice->getHardwareInfo().pSysInfo->CsrSizeInMb * MemoryConstants::megaByte;
uint64_t minCsrAlignment = 2 * 256 * MemoryConstants::kiloByte;
MockGraphicsAllocation csrSurface((void *)minCsrAlignment, minCsrSize);
PreemptionHelper::programCmdStream<FamilyType>(&cmdStream, mode, &csrSurface, nullptr);
PreemptionHelper::programCmdStream<FamilyType>(cmdStream, mode, differentPreemptionMode,
&csrSurface, LinearStream(nullptr, 0), *mockDevice);
HardwareParse cmdParser;
cmdParser.parseCommands<FamilyType>(cmdStream);