From d290955a5739aeb5641729b63c31e10787c98747 Mon Sep 17 00:00:00 2001 From: "Chodor, Jaroslaw" Date: Mon, 8 Jan 2018 15:58:02 +0100 Subject: [PATCH] Preemption - SIP command programming Change-Id: I4c7c805a77a9decb8f13d39055bfb2590209ca3e --- runtime/command_queue/command_queue.cpp | 14 +- .../command_stream_receiver.cpp | 14 +- .../command_stream/command_stream_receiver.h | 8 +- .../command_stream_receiver_hw.h | 8 +- .../command_stream_receiver_hw.inl | 29 ++-- runtime/command_stream/preemption.cpp | 38 ++++- runtime/command_stream/preemption.h | 17 +- runtime/gen8/command_stream_receiver_hw.cpp | 4 +- runtime/gen8/preamble.cpp | 4 +- runtime/gen8/preemption.cpp | 27 ++- runtime/gen9/command_stream_receiver_hw.cpp | 4 +- runtime/gen9/preemption.cpp | 64 +++++-- runtime/helpers/preamble.h | 9 +- runtime/helpers/preamble.inl | 20 ++- .../command_queue/command_queue_tests.cpp | 27 ++- .../command_stream_receiver_hw_tests.cpp | 16 +- .../command_stream_receiver_tests.cpp | 42 ++++- unit_tests/gen8/test_preamble.cpp | 9 +- unit_tests/gen8/test_preemption.cpp | 9 + unit_tests/gen9/skl/test_preamble_skl.cpp | 13 +- unit_tests/gen9/test_preemption.cpp | 44 +++++ unit_tests/mocks/CMakeLists.txt | 3 +- unit_tests/mocks/mock_builtins.h | 61 +++++++ unit_tests/mocks/mock_csr.h | 26 ++- unit_tests/mocks/mock_device.h | 3 +- unit_tests/preamble/CMakeLists.txt | 3 +- unit_tests/preamble/preamble_tests.cpp | 76 +++++++++ unit_tests/preemption/preemption_tests.cpp | 159 +++++++++++++++++- 28 files changed, 661 insertions(+), 90 deletions(-) create mode 100644 unit_tests/mocks/mock_builtins.h create mode 100644 unit_tests/preamble/preamble_tests.cpp diff --git a/runtime/command_queue/command_queue.cpp b/runtime/command_queue/command_queue.cpp index 0fe214ca22..caf95921d5 100644 --- a/runtime/command_queue/command_queue.cpp +++ b/runtime/command_queue/command_queue.cpp @@ -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; diff --git a/runtime/command_stream/command_stream_receiver.cpp b/runtime/command_stream/command_stream_receiver.cpp index 832f1cc5d1..3e3ec59bb8 100644 --- a/runtime/command_stream/command_stream_receiver.cpp +++ b/runtime/command_stream/command_stream_receiver.cpp @@ -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 diff --git a/runtime/command_stream/command_stream_receiver.h b/runtime/command_stream/command_stream_receiver.h index fd42ed1489..3fa8396e2a 100644 --- a/runtime/command_stream/command_stream_receiver.h +++ b/runtime/command_stream/command_stream_receiver.h @@ -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; diff --git a/runtime/command_stream/command_stream_receiver_hw.h b/runtime/command_stream/command_stream_receiver_hw.h index 7064562200..d29ce642bd 100644 --- a/runtime/command_stream/command_stream_receiver_hw.h +++ b/runtime/command_stream/command_stream_receiver_hw.h @@ -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 -size_t getSizeRequiredPreambleCS(const HardwareInfo &hwInfo); +size_t getSizeRequiredPreambleCS(const Device &device); } // namespace OCLRT diff --git a/runtime/command_stream/command_stream_receiver_hw.inl b/runtime/command_stream/command_stream_receiver_hw.inl index f11b5e6551..6bdca919c3 100644 --- a/runtime/command_stream/command_stream_receiver_hw.inl +++ b/runtime/command_stream/command_stream_receiver_hw.inl @@ -67,11 +67,11 @@ inline void CommandStreamReceiverHw::alignToCacheLine(LinearStream &c } template -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::getAdditionalCommandsSize(hwInfo); + sizeof(typename GfxFamily::MEDIA_VFE_STATE) + PreambleHelper::getAdditionalCommandsSize(device); } template @@ -163,11 +163,11 @@ CompletionStamp CommandStreamReceiverHw::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::getScratchPatchAddress() { } template -size_t CommandStreamReceiverHw::getRequiredCsrSize() { - size_t size = getSizeRequiredPreambleCS(hwInfo) + +size_t CommandStreamReceiverHw::getRequiredCmdStreamSize(const DispatchFlags &dispatchFlags) { + size_t size = getSizeRequiredPreambleCS(*memoryManager->device) + sizeof(typename GfxFamily::STATE_BASE_ADDRESS) + sizeof(PIPE_CONTROL) + getRequiredPipeControlSize() + @@ -502,9 +502,8 @@ size_t CommandStreamReceiverHw::getRequiredCsrSize() { } size += getCmdSizeForCoherency(); - if (csrSizeRequestFlags.preemptionRequestChanged) { - size += PreemptionHelper::getRequiredCmdStreamSize(memoryManager->device->getPreemptionMode()); - } + size += PreemptionHelper::getRequiredCmdStreamSize(dispatchFlags.preemptionMode, this->lastPreemptionMode); + return alignUp(size, MemoryConstants::cacheLineSize); } @@ -529,11 +528,11 @@ inline void CommandStreamReceiverHw::waitForTaskCountWithKmdNotifyFal } template -inline void CommandStreamReceiverHw::programPreemption(LinearStream &csr, DispatchFlags &dispatchFlags) { - if (csrSizeRequestFlags.preemptionRequestChanged) { - PreemptionHelper::programCmdStream(&csr, dispatchFlags.preemptionMode, preemptionCsrAllocation, nullptr); - this->lastPreemptionMode = dispatchFlags.preemptionMode; - } +inline void CommandStreamReceiverHw::programPreemption(LinearStream &csr, DispatchFlags &dispatchFlags, + const LinearStream &ih) { + PreemptionHelper::programCmdStream(csr, dispatchFlags.preemptionMode, this->lastPreemptionMode, preemptionCsrAllocation, + ih, *memoryManager->device); + this->lastPreemptionMode = dispatchFlags.preemptionMode; } template @@ -562,7 +561,7 @@ inline void CommandStreamReceiverHw::programMediaSampler(LinearStream template inline void CommandStreamReceiverHw::programPreamble(LinearStream &csr, DispatchFlags &dispatchFlags, uint32_t &newL3Config) { if (!this->isPreambleSent) { - PreambleHelper::programPreamble(&csr, hwInfo, newL3Config, this->requiredThreadArbitrationPolicy); + PreambleHelper::programPreamble(&csr, *memoryManager->device, newL3Config, this->requiredThreadArbitrationPolicy, this->preemptionCsrAllocation); this->isPreambleSent = true; this->lastSentL3Config = newL3Config; this->lastSentThreadAribtrationPolicy = this->requiredThreadArbitrationPolicy; diff --git a/runtime/command_stream/preemption.cpp b/runtime/command_stream/preemption.cpp index f6b6ba76c7..1aaca6f427 100644 --- a/runtime/command_stream/preemption.cpp +++ b/runtime/command_stream/preemption.cpp @@ -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 diff --git a/runtime/command_stream/preemption.h b/runtime/command_stream/preemption.h index e589ebc547..6822d6784f 100644 --- a/runtime/command_stream/preemption.h +++ b/runtime/command_stream/preemption.h @@ -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 - 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 - static size_t getRequiredCmdStreamSize(PreemptionMode preemptionMode); + static size_t getRequiredPreambleSize(const Device &device); + + template + static void programPreamble(LinearStream &preambleCmdStream, const Device &device, const GraphicsAllocation *preemptionCsr); + + template + static size_t getRequiredCmdStreamSize(PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode); + + template + static void programCmdStream(LinearStream &cmdStream, PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode, + GraphicsAllocation *preemptionCsr, const LinearStream &ih, const Device &device); template static size_t getPreemptionWaCsSize(const Device &device); diff --git a/runtime/gen8/command_stream_receiver_hw.cpp b/runtime/gen8/command_stream_receiver_hw.cpp index 2acc94e085..e63672775f 100644 --- a/runtime/gen8/command_stream_receiver_hw.cpp +++ b/runtime/gen8/command_stream_receiver_hw.cpp @@ -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::addDcFlushToPipeControl(Family::PIPE_CONTR pCmd->setDcFlushEnable(flushDC); } -template size_t getSizeRequiredPreambleCS(const HardwareInfo &hwInfo); +template size_t getSizeRequiredPreambleCS(const Device &hwInfo); template <> void populateFactoryTable>() { diff --git a/runtime/gen8/preamble.cpp b/runtime/gen8/preamble.cpp index 939531f204..7a40246a0a 100644 --- a/runtime/gen8/preamble.cpp +++ b/runtime/gen8/preamble.cpp @@ -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::programThreadArbitration(LinearStream *pCommandS } template <> -uint32_t PreambleHelper::getAdditionalCommandsSize(const HardwareInfo &hwInfo) { +uint32_t PreambleHelper::getAdditionalCommandsSize(const Device &device) { return 0; } diff --git a/runtime/gen8/preemption.cpp b/runtime/gen8/preemption.cpp index daca46931e..1111837b26 100644 --- a/runtime/gen8/preemption.cpp +++ b/runtime/gen8/preemption.cpp @@ -35,23 +35,42 @@ static constexpr uint32_t cmdLevelVal = (1 << 2); }; // namespace PreemptionBDW template <> -void PreemptionHelper::programCmdStream(LinearStream *cmdStream, PreemptionMode &preemptionMode, GraphicsAllocation *preemptionCsr, GraphicsAllocation *sipKernel) { +void PreemptionHelper::programCmdStream(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::program(cmdStream, PreemptionBDW::mmioAddress, regVal); + LriHelper::program(&cmdStream, PreemptionBDW::mmioAddress, regVal); } template <> -size_t PreemptionHelper::getRequiredCmdStreamSize(PreemptionMode preemptionMode) { +size_t PreemptionHelper::getRequiredCmdStreamSize(PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode) { + if (newPreemptionMode == oldPreemptionMode) { + return 0; + } return sizeof(typename GfxFamily::MI_LOAD_REGISTER_IMM); } +template <> +size_t PreemptionHelper::getRequiredPreambleSize(const Device &device) { + return 0; +} + +template <> +void PreemptionHelper::programPreamble(LinearStream &preambleCmdStream, const Device &device, + const GraphicsAllocation *preemptionCsr) { +} + template size_t PreemptionHelper::getPreemptionWaCsSize(const Device &device); template void PreemptionHelper::applyPreemptionWaCmdsBegin(LinearStream *pCommandStream, const Device &device); template void PreemptionHelper::applyPreemptionWaCmdsEnd(LinearStream *pCommandStream, const Device &device); + } // namespace OCLRT diff --git a/runtime/gen9/command_stream_receiver_hw.cpp b/runtime/gen9/command_stream_receiver_hw.cpp index 8bdb01c2a1..16c0f5474e 100644 --- a/runtime/gen9/command_stream_receiver_hw.cpp +++ b/runtime/gen9/command_stream_receiver_hw.cpp @@ -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::addDcFlushToPipeControl(Family::PIPE_CONTROL *pCmd, bool flushDC) { } -template size_t getSizeRequiredPreambleCS(const HardwareInfo &hwInfo); +template size_t getSizeRequiredPreambleCS(const Device &device); template <> void populateFactoryTable>() { diff --git a/runtime/gen9/preemption.cpp b/runtime/gen9/preemption.cpp index 61ba4c4f8b..ecfb5cde46 100644 --- a/runtime/gen9/preemption.cpp +++ b/runtime/gen9/preemption.cpp @@ -20,6 +20,9 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include + +#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(LinearStream *cmdStream, PreemptionMode &preemptionMode, GraphicsAllocation *preemptionCsr, GraphicsAllocation *sipKernel) { +void PreemptionHelper::programCmdStream(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::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::program(&cmdStream, PreemptionSKL::mmioAddress, regVal); } template <> -size_t PreemptionHelper::getRequiredCmdStreamSize(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(PreemptionMode newPreemptionMode, PreemptionMode oldPreemptionMode) { + if (newPreemptionMode == oldPreemptionMode) { + return 0; } - return size; + return sizeof(typename GfxFamily::MI_LOAD_REGISTER_IMM); +} + +template <> +size_t PreemptionHelper::getRequiredPreambleSize(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(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(preambleCmdStream.getSpace(sizeof(GPGPU_CSR_BASE_ADDRESS))); + csr->init(); + csr->setGpgpuCsrBaseAddress(preemptionCsr->getGpuAddressToPatch()); + + auto sip = reinterpret_cast(preambleCmdStream.getSpace(sizeof(STATE_SIP))); + sip->init(); + sip->setSystemInstructionPointer(0); } template size_t PreemptionHelper::getPreemptionWaCsSize(const Device &device); diff --git a/runtime/helpers/preamble.h b/runtime/helpers/preamble.h index 515c542604..92ae44d509 100644 --- a/runtime/helpers/preamble.h +++ b/runtime/helpers/preamble.h @@ -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 @@ -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(); }; diff --git a/runtime/helpers/preamble.inl b/runtime/helpers/preamble.inl index 47c54c4f38..a53161023f 100644 --- a/runtime/helpers/preamble.inl +++ b/runtime/helpers/preamble.inl @@ -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::programGenSpecificPreambleWorkArounds(LinearStre } template -uint32_t PreambleHelper::getAdditionalCommandsSize(const HardwareInfo &hwInfo) { +uint32_t PreambleHelper::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(device); + return static_cast(requiredSize); } template @@ -105,11 +108,18 @@ void PreambleHelper::programL3(LinearStream *pCommandStream, uint32_t } template -void PreambleHelper::programPreamble(LinearStream *pCommandStream, const HardwareInfo &hwInfo, uint32_t l3Config, uint32_t requiredThreadArbitrationPolicy) { +void PreambleHelper::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 +void PreambleHelper::programPreemption(LinearStream *pCommandStream, const Device &device, GraphicsAllocation *preemptionCsr) { + PreemptionHelper::programPreamble(*pCommandStream, device, preemptionCsr); } template diff --git a/unit_tests/command_queue/command_queue_tests.cpp b/unit_tests/command_queue/command_queue_tests.cpp index 97f1b526f3..9fc7bc77c2 100644 --- a/unit_tests/command_queue/command_queue_tests.cpp +++ b/unit_tests/command_queue/command_queue_tests.cpp @@ -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(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::create(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(heap.getBase()); + auto dataFoundInReservedBlock = ArrayRef(reservedBlock, sizeof(pattern)); + auto expectedData = ArrayRef(csr->instructionHeapReserveredData); + EXPECT_THAT(dataFoundInReservedBlock, testing::ContainerEq(expectedData)); +} diff --git a/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp b/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp index 3c860c2d98..7ac6c52636 100644 --- a/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp +++ b/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp @@ -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(commandStreamReceiver.hwInfo); + size_t sizeNeededForPreamble = getSizeRequiredPreambleCS(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(commandStreamReceiver.hwInfo); + size_t sizeNeededForPreamble = getSizeRequiredPreambleCS(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(commandStreamReceiver.hwInfo) + + size_t sizeNeeded = getSizeRequiredPreambleCS(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); diff --git a/unit_tests/command_stream/command_stream_receiver_tests.cpp b/unit_tests/command_stream/command_stream_receiver_tests.cpp index eb99498ea0..f402c42b3a 100644 --- a/unit_tests/command_stream/command_stream_receiver_tests.cpp +++ b/unit_tests/command_stream/command_stream_receiver_tests.cpp @@ -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(); 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::create(nullptr)); + mockDevice->setPreemptionMode(PreemptionMode::MidThread); + + { + MockBuiltins mockBuiltins; + mockBuiltins.overrideGlobalBuiltins(); + { + auto sipOverride = std::unique_ptr(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 cmdStreamIhBuffer; + cmdStreamIhBuffer.resize(reservedSize); + LinearStream cmdStreamReceiverInstrucionHeap{cmdStreamIhBuffer.begin(), cmdStreamIhBuffer.size()}; + mockDevice->getCommandStreamReceiver().initializeInstructionHeapCmdStreamReceiverReservedBlock(cmdStreamReceiverInstrucionHeap); + + StackVec preemptionHelperIhBuffer; + preemptionHelperIhBuffer.resize(expectedSize); + LinearStream preemptionHelperInstrucionHeap{preemptionHelperIhBuffer.begin(), preemptionHelperIhBuffer.size()}; + PreemptionHelper::initializeInstructionHeapSipKernelReservedBlock(preemptionHelperInstrucionHeap, *mockDevice); + + cmdStreamIhBuffer.resize(expectedSize); + EXPECT_THAT(preemptionHelperIhBuffer, testing::ContainerEq(cmdStreamIhBuffer)); + } +} diff --git a/unit_tests/gen8/test_preamble.cpp b/unit_tests/gen8/test_preamble.cpp index 43456cdcda..2aedf4a671 100644 --- a/unit_tests/gen8/test_preamble.cpp +++ b/unit_tests/gen8/test_preamble.cpp @@ -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::getL3Config(**platformDevices, true); - PreambleHelper::programPreamble(&linearStream, **platformDevices, l3Config, ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin); + + PreambleHelper::programPreamble(&linearStream, MockDevice(**platformDevices), l3Config, + ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin, + nullptr); parseCommands(cs); @@ -84,7 +87,7 @@ BDWTEST_F(ThreadArbitrationGen8, givenPreambleWhenItIsProgrammedThenThreadArbitr EXPECT_EQ(RegisterOffset, lri.getRegisterOffset()); EXPECT_EQ(1u, lri.getDataDword() & 1); - EXPECT_EQ(0u, PreambleHelper::getAdditionalCommandsSize(**platformDevices)); + EXPECT_EQ(0u, PreambleHelper::getAdditionalCommandsSize(MockDevice(**platformDevices))); } typedef PreambleFixture Gen8UrbEntryAllocationSize; diff --git a/unit_tests/gen8/test_preemption.cpp b/unit_tests/gen8/test_preemption.cpp index 433399c63d..1b21f73928 100644 --- a/unit_tests/gen8/test_preemption.cpp +++ b/unit_tests/gen8/test_preemption.cpp @@ -50,6 +50,15 @@ GEN8TEST_F(Gen8PreemptionTests, allowThreadGroupPreemptionReturnsTrue) { EXPECT_TRUE(PreemptionHelper::allowThreadGroupPreemption(kernel.get(), waTable)); } +GEN8TEST_F(Gen8PreemptionTests, doesNotProgramPreamble) { + size_t requiredSize = PreemptionHelper::getRequiredPreambleSize(*device); + EXPECT_EQ(0U, requiredSize); + + LinearStream cmdStream{nullptr, 0}; + PreemptionHelper::programPreamble(cmdStream, *device, nullptr); + EXPECT_EQ(0U, cmdStream.getUsed()); +} + GEN8TEST_F(Gen8PreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogram) { pDevice->setPreemptionMode(PreemptionMode::ThreadGroup); auto &csr = pDevice->getUltCommandStreamReceiver(); diff --git a/unit_tests/gen9/skl/test_preamble_skl.cpp b/unit_tests/gen9/skl/test_preamble_skl.cpp index a76a6c384b..08def96b0b 100644 --- a/unit_tests/gen9/skl/test_preamble_skl.cpp +++ b/unit_tests/gen9/skl/test_preamble_skl.cpp @@ -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::getL3Config(**platformDevices, true); - PreambleHelper::programPreamble(&linearStream, **platformDevices, l3Config, ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin); + PreambleHelper::programPreamble(&linearStream, MockDevice(**platformDevices), l3Config, + ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin, + nullptr); parseCommands(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::getAdditionalCommandsSize(hwInfo)); + EXPECT_EQ(sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL), + PreambleHelper::getAdditionalCommandsSize(MockDevice(*platformDevices[0]))); } GEN9TEST_F(PreambleVfeState, WaOff) { diff --git a/unit_tests/gen9/test_preemption.cpp b/unit_tests/gen9/test_preemption.cpp index 7ba9721b5e..3cc9b56c0b 100644 --- a/unit_tests/gen9/test_preemption.cpp +++ b/unit_tests/gen9/test_preemption.cpp @@ -60,6 +60,50 @@ PreemptionTestHwDetails GetPreemptionTestHwDetails() { return ret; } +GEN9TEST_F(Gen9PreemptionTests, whenMidThreadPreemptionIsNotAvailableThenDoesNotProgramPreamble) { + device->setPreemptionMode(PreemptionMode::ThreadGroup); + + size_t requiredSize = PreemptionHelper::getRequiredPreambleSize(*device); + EXPECT_EQ(0U, requiredSize); + + LinearStream cmdStream{nullptr, 0}; + PreemptionHelper::programPreamble(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(*device); + size_t expectedPreambleSize = sizeof(GPGPU_CSR_BASE_ADDRESS) + sizeof(STATE_SIP); + EXPECT_EQ(expectedPreambleSize, requiredPreambleSize); + + StackVec preambleStorage(requiredPreambleSize); + ASSERT_LE(requiredPreambleSize, preambleStorage.size()); + LinearStream preambleCmdStream{preambleStorage.begin(), preambleStorage.size()}; + PreemptionHelper::programPreamble(preambleCmdStream, *device, &csrSurface); + + HardwareParse hwParsePreamble; + hwParsePreamble.parseCommands(preambleCmdStream); + + auto csrBaseAddressCmd = hwParsePreamble.getCommand(); + ASSERT_NE(nullptr, csrBaseAddressCmd); + EXPECT_EQ(csrSurface.getGpuAddressToPatch(), csrBaseAddressCmd->getGpgpuCsrBaseAddress()); + + auto stateSipCmd = hwParsePreamble.getCommand(); + ASSERT_NE(nullptr, stateSipCmd); + EXPECT_EQ(0U, stateSipCmd->getSystemInstructionPointer()); +} + GEN9TEST_F(Gen9ThreadGroupPreemptionEnqueueKernelTest, givenSecondEnqueueWithTheSamePreemptionRequestThenDontReprogramThreadGroupNoWa) { pDevice->setPreemptionMode(PreemptionMode::ThreadGroup); WhitelistedRegisters regs = {}; diff --git a/unit_tests/mocks/CMakeLists.txt b/unit_tests/mocks/CMakeLists.txt index 513963bafe..d994003f9c 100644 --- a/unit_tests/mocks/CMakeLists.txt +++ b/unit_tests/mocks/CMakeLists.txt @@ -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" diff --git a/unit_tests/mocks/mock_builtins.h b/unit_tests/mocks/mock_builtins.h new file mode 100644 index 0000000000..27f799ff0b --- /dev/null +++ b/unit_tests/mocks/mock_builtins.h @@ -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 + +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 kernel) { + sipKernelsOverride[kernel->getType()] = std::move(kernel); + } + + OCLRT::BuiltIns *originalGlobalBuiltins = nullptr; + std::map> sipKernelsOverride; +}; diff --git a/unit_tests/mocks/mock_csr.h b/unit_tests/mocks/mock_csr.h index 04be44f024..739a74d865 100644 --- a/unit_tests/mocks/mock_csr.h +++ b/unit_tests/mocks/mock_csr.h @@ -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 @@ -198,6 +199,10 @@ class MockCommandStreamReceiver : public CommandStreamReceiver { public: using CommandStreamReceiver::latestSentTaskCount; using CommandStreamReceiver::tagAddress; + std::vector 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()); + } }; diff --git a/unit_tests/mocks/mock_device.h b/unit_tests/mocks/mock_device.h index f360ee1ad1..8e1a406161 100644 --- a/unit_tests/mocks/mock_device.h +++ b/unit_tests/mocks/mock_device.h @@ -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); diff --git a/unit_tests/preamble/CMakeLists.txt b/unit_tests/preamble/CMakeLists.txt index f36ce57cf2..81b3091f5a 100644 --- a/unit_tests/preamble/CMakeLists.txt +++ b/unit_tests/preamble/CMakeLists.txt @@ -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) diff --git a/unit_tests/preamble/preamble_tests.cpp b/unit_tests/preamble/preamble_tests.cpp new file mode 100644 index 0000000000..340df4df17 --- /dev/null +++ b/unit_tests/preamble/preamble_tests.cpp @@ -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 + +#include + +using PreambleTest = ::testing::Test; + +using namespace OCLRT; + +HWTEST_F(PreambleTest, PreemptionIsTakenIntoAccountWhenProgrammingPreamble) { + auto mockDevice = std::unique_ptr(MockDevice::create(nullptr)); + + mockDevice->setPreemptionMode(PreemptionMode::MidThread); + uint32_t cmdSizePreambleMidThread = PreambleHelper::getAdditionalCommandsSize(*mockDevice); + uint32_t cmdSizePreemptionMidThread = static_cast(PreemptionHelper::getRequiredPreambleSize(*mockDevice)); + + mockDevice->setPreemptionMode(PreemptionMode::Disabled); + uint32_t cmdSizePreambleDisabled = PreambleHelper::getAdditionalCommandsSize(*mockDevice); + uint32_t cmdSizePreemptionDisabled = static_cast(PreemptionHelper::getRequiredPreambleSize(*mockDevice)); + + EXPECT_LE(cmdSizePreemptionMidThread, cmdSizePreambleMidThread); + EXPECT_LE(cmdSizePreemptionDisabled, cmdSizePreambleDisabled); + + EXPECT_LE(cmdSizePreemptionDisabled, cmdSizePreemptionMidThread); + EXPECT_LE((cmdSizePreemptionMidThread - cmdSizePreemptionDisabled), (cmdSizePreambleMidThread - cmdSizePreambleDisabled)); + + mockDevice->setPreemptionMode(PreemptionMode::MidThread); + StackVec preambleBuffer(8192); + LinearStream preambleStream(&*preambleBuffer.begin(), preambleBuffer.size()); + + StackVec preemptionBuffer; + preemptionBuffer.resize(cmdSizePreemptionMidThread); + LinearStream preemptionStream(&*preemptionBuffer.begin(), preemptionBuffer.size()); + + uintptr_t minCsrAlignment = 2 * 256 * MemoryConstants::kiloByte; + MockGraphicsAllocation csrSurface(reinterpret_cast(minCsrAlignment), 1024); + + PreambleHelper::programPreamble(&preambleStream, *mockDevice, 0U, + ThreadArbitrationPolicy::threadArbirtrationPolicyRoundRobin, &csrSurface); + + PreemptionHelper::programPreamble(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); +} diff --git a/unit_tests/preemption/preemption_tests.cpp b/unit_tests/preemption/preemption_tests.cpp index cba22b44a5..e12e442687 100644 --- a/unit_tests/preemption/preemption_tests.cpp +++ b/unit_tests/preemption/preemption_tests.cpp @@ -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::create(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::create(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(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::create(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(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::create(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(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::create(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(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 { }; +HWTEST_P(PreemptionHwTest, getRequiredCmdStreamSizeReturns0WhenPreemptionModeIsNotChanging) { + PreemptionMode mode = GetParam(); + size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize(mode, mode); + EXPECT_EQ(0U, requiredSize); + + StackVec buffer(requiredSize); + LinearStream cmdStream(buffer.begin(), buffer.size()); + + auto mockDevice = std::unique_ptr(MockDevice::create(nullptr)); + { + MockBuiltins tmpBuiltins; + char sipData[16] = {0}; + tmpBuiltins.overrideSipKernel(std::unique_ptr(new OCLRT::SipKernel{SipKernelType::Csr, sipData, sizeof(sipData)})); + tmpBuiltins.overrideGlobalBuiltins(); + PreemptionHelper::programCmdStream(cmdStream, mode, mode, + nullptr, LinearStream(nullptr, 0), *mockDevice); + } + EXPECT_EQ(0U, cmdStream.getUsed()); +} + HWTEST_P(PreemptionHwTest, getRequiredCmdStreamSizeReturnsSizeOfMiLoadRegisterImmWhenPreemptionModeIsChanging) { PreemptionMode mode = GetParam(); + PreemptionMode differentPreemptionMode = static_cast(0); if (false == GetPreemptionTestHwDetails().supportsPreemptionProgramming()) { - EXPECT_EQ(0U, PreemptionHelper::getRequiredCmdStreamSize(mode)); + EXPECT_EQ(0U, PreemptionHelper::getRequiredCmdStreamSize(mode, differentPreemptionMode)); return; } using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM; - size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize(mode); - EXPECT_LE(sizeof(MI_LOAD_REGISTER_IMM), requiredSize); + size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize(mode, differentPreemptionMode); + EXPECT_EQ(sizeof(MI_LOAD_REGISTER_IMM), requiredSize); StackVec 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(&cmdStream, mode, &csrSurface, nullptr); + PreemptionHelper::programCmdStream(cmdStream, mode, differentPreemptionMode, + nullptr, LinearStream(nullptr, 0), *mockDevice); EXPECT_EQ(requiredSize, cmdStream.getUsed()); } HWTEST_P(PreemptionHwTest, programCmdStreamAddsProperMiLoadRegisterImmCommandToTheStream) { PreemptionMode mode = GetParam(); + PreemptionMode differentPreemptionMode = static_cast(0); + auto mockDevice = std::unique_ptr(MockDevice::create(nullptr)); if (false == GetPreemptionTestHwDetails().supportsPreemptionProgramming()) { LinearStream cmdStream(nullptr, 0U); - PreemptionHelper::programCmdStream(&cmdStream, mode, nullptr, nullptr); + LinearStream instructionHeap(nullptr, 0U); + PreemptionHelper::programCmdStream(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(mode); + size_t requiredSize = PreemptionHelper::getRequiredCmdStreamSize(mode, differentPreemptionMode); StackVec buffer(requiredSize); LinearStream cmdStream(buffer.begin(), buffer.size()); - auto mockDevice = std::unique_ptr(MockDevice::create(nullptr)); - size_t minCsrSize = mockDevice->getHardwareInfo().pSysInfo->CsrSizeInMb * MemoryConstants::megaByte; uint64_t minCsrAlignment = 2 * 256 * MemoryConstants::kiloByte; MockGraphicsAllocation csrSurface((void *)minCsrAlignment, minCsrSize); - PreemptionHelper::programCmdStream(&cmdStream, mode, &csrSurface, nullptr); + PreemptionHelper::programCmdStream(cmdStream, mode, differentPreemptionMode, + &csrSurface, LinearStream(nullptr, 0), *mockDevice); HardwareParse cmdParser; cmdParser.parseCommands(cmdStream);