Enhance GPU breakpoint capabilities

Change-Id: Id28afb7ab584eeb5063c7311fed41d7a31edbec7
Signed-off-by: Bartosz Dunajski <bartosz.dunajski@intel.com>
This commit is contained in:
Bartosz Dunajski
2020-09-24 10:52:53 +02:00
committed by sys_ocldev
parent 8d0df0c8a7
commit f92f01e190
8 changed files with 458 additions and 174 deletions

View File

@ -6,6 +6,7 @@
*/
#pragma once
#include "shared/source/helpers/pause_on_gpu_properties.h"
#include "shared/source/memory_manager/internal_allocation_storage.h"
#include "opencl/source/command_queue/gpgpu_walker.h"
@ -121,7 +122,10 @@ void HardwareInterface<GfxFamily>::dispatchWalker(
DEBUG_BREAK_IF(offsetInterfaceDescriptorTable % 64 != 0);
dispatchProfilingPerfStartCommands(hwTimeStamps, hwPerfCounter, commandStream, commandQueue);
dispatchDebugPauseCommands(commandStream, commandQueue, DebugPauseState::waitingForUserStartConfirmation, DebugPauseState::hasUserStartConfirmation);
if (PauseOnGpuProperties::pauseModeAllowed(DebugManager.flags.PauseOnEnqueue.get(), commandQueue.getGpgpuCommandStreamReceiver().peekTaskCount(), PauseOnGpuProperties::PauseMode::BeforeWorkload)) {
dispatchDebugPauseCommands(commandStream, commandQueue, DebugPauseState::waitingForUserStartConfirmation, DebugPauseState::hasUserStartConfirmation);
}
size_t currentDispatchIndex = 0;
for (auto &dispatchInfo : multiDispatchInfo) {
@ -144,7 +148,10 @@ void HardwareInterface<GfxFamily>::dispatchWalker(
HardwareCommandsHelper<GfxFamily>::programCacheFlushAfterWalkerCommand(commandStream, commandQueue, mainKernel, postSyncAddress);
}
dispatchDebugPauseCommands(commandStream, commandQueue, DebugPauseState::waitingForUserEndConfirmation, DebugPauseState::hasUserEndConfirmation);
if (PauseOnGpuProperties::pauseModeAllowed(DebugManager.flags.PauseOnEnqueue.get(), commandQueue.getGpgpuCommandStreamReceiver().peekTaskCount(), PauseOnGpuProperties::PauseMode::AfterWorkload)) {
dispatchDebugPauseCommands(commandStream, commandQueue, DebugPauseState::waitingForUserEndConfirmation, DebugPauseState::hasUserEndConfirmation);
}
dispatchProfilingPerfEndCommands(hwTimeStamps, hwPerfCounter, commandStream, commandQueue);
}
@ -283,8 +290,7 @@ inline void HardwareInterface<GfxFamily>::dispatchDebugPauseCommands(
DebugPauseState confirmationTrigger,
DebugPauseState waitCondition) {
if (static_cast<int32_t>(commandQueue.getGpgpuCommandStreamReceiver().peekTaskCount()) == DebugManager.flags.PauseOnEnqueue.get() &&
!commandQueue.isSpecial()) {
if (!commandQueue.isSpecial()) {
auto address = commandQueue.getGpgpuCommandStreamReceiver().getDebugPauseStateGPUAddress();
{
using PIPE_CONTROL = typename GfxFamily::PIPE_CONTROL;

View File

@ -5,6 +5,7 @@
*
*/
#include "shared/source/helpers/pause_on_gpu_properties.h"
#include "shared/source/helpers/vec.h"
#include "shared/test/unit_test/cmd_parse/hw_parse.h"
#include "shared/test/unit_test/helpers/debug_manager_state_restore.h"
@ -863,84 +864,219 @@ HWTEST_TEMPLATED_F(BlitEnqueueWithNoTimestampPacketTests, givenNoTimestampPacket
verifySemaphore<FamilyType>(cmdFound, bcsSignalAddress);
}
using BlitEnqueueWithDebugCapabilityTests = BlitEnqueueTests<0>;
struct BlitEnqueueWithDebugCapabilityTests : public BlitEnqueueTests<0> {
template <typename MI_SEMAPHORE_WAIT>
void findSemaphores(GenCmdList &cmdList) {
auto semaphore = find<MI_SEMAPHORE_WAIT *>(cmdList.begin(), cmdList.end());
while (semaphore != cmdList.end()) {
auto semaphoreCmd = genCmdCast<MI_SEMAPHORE_WAIT *>(*semaphore);
if (static_cast<uint32_t>(DebugPauseState::hasUserStartConfirmation) == semaphoreCmd->getSemaphoreDataDword() &&
debugPauseStateAddress == semaphoreCmd->getSemaphoreGraphicsAddress()) {
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_EQUAL_SDD, semaphoreCmd->getCompareOperation());
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, semaphoreCmd->getWaitMode());
semaphoreBeforeCopyFound++;
}
if (static_cast<uint32_t>(DebugPauseState::hasUserEndConfirmation) == semaphoreCmd->getSemaphoreDataDword() &&
debugPauseStateAddress == semaphoreCmd->getSemaphoreGraphicsAddress()) {
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_EQUAL_SDD, semaphoreCmd->getCompareOperation());
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, semaphoreCmd->getWaitMode());
semaphoreAfterCopyFound++;
}
semaphore = find<MI_SEMAPHORE_WAIT *>(++semaphore, cmdList.end());
}
}
template <typename MI_FLUSH_DW>
void findMiFlushes(GenCmdList &cmdList) {
auto miFlush = find<MI_FLUSH_DW *>(cmdList.begin(), cmdList.end());
while (miFlush != cmdList.end()) {
auto miFlushCmd = genCmdCast<MI_FLUSH_DW *>(*miFlush);
if (static_cast<uint32_t>(DebugPauseState::waitingForUserStartConfirmation) == miFlushCmd->getImmediateData() &&
debugPauseStateAddress == miFlushCmd->getDestinationAddress()) {
EXPECT_EQ(MI_FLUSH_DW::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA_QWORD, miFlushCmd->getPostSyncOperation());
miFlushBeforeCopyFound++;
}
if (static_cast<uint32_t>(DebugPauseState::waitingForUserEndConfirmation) == miFlushCmd->getImmediateData() &&
debugPauseStateAddress == miFlushCmd->getDestinationAddress()) {
EXPECT_EQ(MI_FLUSH_DW::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA_QWORD, miFlushCmd->getPostSyncOperation());
miFlushAfterCopyFound++;
}
miFlush = find<MI_FLUSH_DW *>(++miFlush, cmdList.end());
}
}
uint32_t semaphoreBeforeCopyFound = 0;
uint32_t semaphoreAfterCopyFound = 0;
uint32_t miFlushBeforeCopyFound = 0;
uint32_t miFlushAfterCopyFound = 0;
ReleaseableObjectPtr<Buffer> buffer;
uint64_t debugPauseStateAddress = 0;
int hostPtr = 0;
};
HWTEST_TEMPLATED_F(BlitEnqueueWithDebugCapabilityTests, givenDebugFlagSetWhenDispatchingBlitEnqueueThenAddPausingCommands) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using MI_FLUSH_DW = typename FamilyType::MI_FLUSH_DW;
DebugManager.flags.PauseOnBlitCopy.set(1);
auto ultBcsCsr = static_cast<UltCommandStreamReceiver<FamilyType> *>(bcsCsr);
auto debugPauseStateAddress = ultBcsCsr->getDebugPauseStateGPUAddress();
debugPauseStateAddress = ultBcsCsr->getDebugPauseStateGPUAddress();
auto buffer = createBuffer(1, false);
buffer = createBuffer(1, false);
buffer->forceDisallowCPUCopy = true;
int hostPtr = 0;
DebugManager.flags.PauseOnBlitCopy.set(1);
commandQueue->enqueueWriteBuffer(buffer.get(), true, 0, 1, &hostPtr, nullptr, 0, nullptr, nullptr);
commandQueue->enqueueWriteBuffer(buffer.get(), true, 0, 1, &hostPtr, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(ultBcsCsr->commandStream);
auto &cmdList = hwParser.cmdList;
auto semaphore = find<MI_SEMAPHORE_WAIT *>(cmdList.begin(), cmdList.end());
bool semaphoreBeforeCopyFound = false;
bool semaphoreAfterCopyFound = false;
while (semaphore != cmdList.end()) {
auto semaphoreCmd = genCmdCast<MI_SEMAPHORE_WAIT *>(*semaphore);
if (static_cast<uint32_t>(DebugPauseState::hasUserStartConfirmation) == semaphoreCmd->getSemaphoreDataDword()) {
EXPECT_EQ(debugPauseStateAddress, semaphoreCmd->getSemaphoreGraphicsAddress());
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_EQUAL_SDD, semaphoreCmd->getCompareOperation());
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, semaphoreCmd->getWaitMode());
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
semaphoreBeforeCopyFound = true;
}
EXPECT_EQ(1u, semaphoreBeforeCopyFound);
EXPECT_EQ(1u, semaphoreAfterCopyFound);
if (static_cast<uint32_t>(DebugPauseState::hasUserEndConfirmation) == semaphoreCmd->getSemaphoreDataDword()) {
EXPECT_TRUE(semaphoreBeforeCopyFound);
EXPECT_EQ(debugPauseStateAddress, semaphoreCmd->getSemaphoreGraphicsAddress());
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_EQUAL_SDD, semaphoreCmd->getCompareOperation());
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, semaphoreCmd->getWaitMode());
findMiFlushes<MI_FLUSH_DW>(hwParser.cmdList);
semaphoreAfterCopyFound = true;
break;
}
EXPECT_EQ(1u, miFlushBeforeCopyFound);
EXPECT_EQ(1u, miFlushAfterCopyFound);
}
semaphore = find<MI_SEMAPHORE_WAIT *>(++semaphore, cmdList.end());
}
HWTEST_TEMPLATED_F(BlitEnqueueWithDebugCapabilityTests, givenDebugFlagSetToMinusTwoWhenDispatchingBlitEnqueueThenAddPausingCommandsForEachEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using MI_FLUSH_DW = typename FamilyType::MI_FLUSH_DW;
EXPECT_TRUE(semaphoreAfterCopyFound);
auto ultBcsCsr = static_cast<UltCommandStreamReceiver<FamilyType> *>(bcsCsr);
auto miFlush = find<MI_FLUSH_DW *>(cmdList.begin(), cmdList.end());
bool miFlushBeforeCopyFound = false;
bool miFlushAfterCopyFound = false;
while (miFlush != cmdList.end()) {
auto miFlushCmd = genCmdCast<MI_FLUSH_DW *>(*miFlush);
if (static_cast<uint32_t>(DebugPauseState::waitingForUserStartConfirmation) == miFlushCmd->getImmediateData() &&
debugPauseStateAddress == miFlushCmd->getDestinationAddress()) {
debugPauseStateAddress = ultBcsCsr->getDebugPauseStateGPUAddress();
EXPECT_EQ(MI_FLUSH_DW::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA_QWORD, miFlushCmd->getPostSyncOperation());
buffer = createBuffer(1, false);
buffer->forceDisallowCPUCopy = true;
miFlushBeforeCopyFound = true;
}
DebugManager.flags.PauseOnBlitCopy.set(-2);
if (static_cast<uint32_t>(DebugPauseState::waitingForUserEndConfirmation) == miFlushCmd->getImmediateData() &&
debugPauseStateAddress == miFlushCmd->getDestinationAddress()) {
EXPECT_TRUE(miFlushBeforeCopyFound);
commandQueue->enqueueWriteBuffer(buffer.get(), true, 0, 1, &hostPtr, nullptr, 0, nullptr, nullptr);
commandQueue->enqueueWriteBuffer(buffer.get(), true, 0, 1, &hostPtr, nullptr, 0, nullptr, nullptr);
EXPECT_EQ(MI_FLUSH_DW::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA_QWORD, miFlushCmd->getPostSyncOperation());
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(ultBcsCsr->commandStream);
miFlushAfterCopyFound = true;
break;
}
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
miFlush = find<MI_FLUSH_DW *>(++miFlush, cmdList.end());
}
EXPECT_EQ(2u, semaphoreBeforeCopyFound);
EXPECT_EQ(2u, semaphoreAfterCopyFound);
EXPECT_TRUE(miFlushAfterCopyFound);
findMiFlushes<MI_FLUSH_DW>(hwParser.cmdList);
EXPECT_EQ(2u, miFlushBeforeCopyFound);
EXPECT_EQ(2u, miFlushAfterCopyFound);
}
HWTEST_TEMPLATED_F(BlitEnqueueWithDebugCapabilityTests, givenPauseModeSetToBeforeOnlyWhenDispatchingBlitEnqueueThenAddPauseCommandsOnlyBeforeEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using MI_FLUSH_DW = typename FamilyType::MI_FLUSH_DW;
auto ultBcsCsr = static_cast<UltCommandStreamReceiver<FamilyType> *>(bcsCsr);
debugPauseStateAddress = ultBcsCsr->getDebugPauseStateGPUAddress();
buffer = createBuffer(1, false);
buffer->forceDisallowCPUCopy = true;
DebugManager.flags.PauseOnBlitCopy.set(0);
DebugManager.flags.PauseOnGpuMode.set(PauseOnGpuProperties::PauseMode::BeforeWorkload);
commandQueue->enqueueWriteBuffer(buffer.get(), true, 0, 1, &hostPtr, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(ultBcsCsr->commandStream);
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
EXPECT_EQ(1u, semaphoreBeforeCopyFound);
EXPECT_EQ(0u, semaphoreAfterCopyFound);
findMiFlushes<MI_FLUSH_DW>(hwParser.cmdList);
EXPECT_EQ(1u, miFlushBeforeCopyFound);
EXPECT_EQ(0u, miFlushAfterCopyFound);
}
HWTEST_TEMPLATED_F(BlitEnqueueWithDebugCapabilityTests, givenPauseModeSetToAfterOnlyWhenDispatchingBlitEnqueueThenAddPauseCommandsOnlyAfterEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using MI_FLUSH_DW = typename FamilyType::MI_FLUSH_DW;
auto ultBcsCsr = static_cast<UltCommandStreamReceiver<FamilyType> *>(bcsCsr);
debugPauseStateAddress = ultBcsCsr->getDebugPauseStateGPUAddress();
buffer = createBuffer(1, false);
buffer->forceDisallowCPUCopy = true;
DebugManager.flags.PauseOnBlitCopy.set(0);
DebugManager.flags.PauseOnGpuMode.set(PauseOnGpuProperties::PauseMode::AfterWorkload);
commandQueue->enqueueWriteBuffer(buffer.get(), true, 0, 1, &hostPtr, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(ultBcsCsr->commandStream);
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
EXPECT_EQ(0u, semaphoreBeforeCopyFound);
EXPECT_EQ(1u, semaphoreAfterCopyFound);
findMiFlushes<MI_FLUSH_DW>(hwParser.cmdList);
EXPECT_EQ(0u, miFlushBeforeCopyFound);
EXPECT_EQ(1u, miFlushAfterCopyFound);
}
HWTEST_TEMPLATED_F(BlitEnqueueWithDebugCapabilityTests, givenPauseModeSetToBeforeAndAfterWorkloadWhenDispatchingBlitEnqueueThenAddPauseCommandsAroundEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using MI_FLUSH_DW = typename FamilyType::MI_FLUSH_DW;
auto ultBcsCsr = static_cast<UltCommandStreamReceiver<FamilyType> *>(bcsCsr);
debugPauseStateAddress = ultBcsCsr->getDebugPauseStateGPUAddress();
buffer = createBuffer(1, false);
buffer->forceDisallowCPUCopy = true;
DebugManager.flags.PauseOnBlitCopy.set(0);
DebugManager.flags.PauseOnGpuMode.set(PauseOnGpuProperties::PauseMode::BeforeAndAfterWorkload);
commandQueue->enqueueWriteBuffer(buffer.get(), true, 0, 1, &hostPtr, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(ultBcsCsr->commandStream);
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
EXPECT_EQ(1u, semaphoreBeforeCopyFound);
EXPECT_EQ(1u, semaphoreAfterCopyFound);
findMiFlushes<MI_FLUSH_DW>(hwParser.cmdList);
EXPECT_EQ(1u, miFlushBeforeCopyFound);
EXPECT_EQ(1u, miFlushAfterCopyFound);
}
HWTEST_TEMPLATED_F(BlitEnqueueWithDebugCapabilityTests, givenDebugFlagSetWhenCreatingCsrThenCreateDebugThread) {

View File

@ -5,6 +5,7 @@
*
*/
#include "shared/source/helpers/pause_on_gpu_properties.h"
#include "shared/test/unit_test/cmd_parse/hw_parse.h"
#include "shared/test/unit_test/helpers/debug_manager_state_restore.h"
@ -1291,151 +1292,240 @@ HWTEST_F(EnqueueKernelTest, whenEnqueueKernelWithEngineHintsThenEpilogRequiredIs
EXPECT_EQ(csr.recordedDispatchFlags.engineHints, 1u);
}
HWTEST_F(EnqueueKernelTest, givenPauseOnEnqueueFlagSetWhenDispatchWalkersThenInsertPauseCommandsAroundSpecifiedEnqueue) {
using WALKER_TYPE = typename FamilyType::WALKER_TYPE;
struct PauseOnGpuTests : public EnqueueKernelTest {
void SetUp() override {
EnqueueKernelTest::SetUp();
auto &csr = pDevice->getGpgpuCommandStreamReceiver();
debugPauseStateAddress = csr.getDebugPauseStateGPUAddress();
}
template <typename MI_SEMAPHORE_WAIT>
bool verifySemaphore(const GenCmdList::iterator &iterator, uint64_t debugPauseStateAddress, DebugPauseState requiredDebugPauseState) {
auto semaphoreCmd = genCmdCast<MI_SEMAPHORE_WAIT *>(*iterator);
if ((static_cast<uint32_t>(requiredDebugPauseState) == semaphoreCmd->getSemaphoreDataDword()) &&
(debugPauseStateAddress == semaphoreCmd->getSemaphoreGraphicsAddress())) {
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_EQUAL_SDD, semaphoreCmd->getCompareOperation());
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, semaphoreCmd->getWaitMode());
return true;
}
return false;
}
template <typename PIPE_CONTROL>
bool verifyPipeControl(const GenCmdList::iterator &iterator, uint64_t debugPauseStateAddress, DebugPauseState requiredDebugPauseState) {
auto pipeControlCmd = genCmdCast<PIPE_CONTROL *>(*iterator);
if ((static_cast<uint32_t>(requiredDebugPauseState) == pipeControlCmd->getImmediateData()) &&
(static_cast<uint32_t>(debugPauseStateAddress & 0x0000FFFFFFFFULL) == pipeControlCmd->getAddress()) &&
(static_cast<uint32_t>(debugPauseStateAddress >> 32) == pipeControlCmd->getAddressHigh())) {
EXPECT_TRUE(pipeControlCmd->getCommandStreamerStallEnable());
EXPECT_TRUE(pipeControlCmd->getDcFlushEnable());
EXPECT_EQ(PIPE_CONTROL::POST_SYNC_OPERATION::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA, pipeControlCmd->getPostSyncOperation());
return true;
}
return false;
}
template <typename MI_SEMAPHORE_WAIT>
void findSemaphores(GenCmdList &cmdList) {
auto semaphore = find<MI_SEMAPHORE_WAIT *>(cmdList.begin(), cmdList.end());
while (semaphore != cmdList.end()) {
if (verifySemaphore<MI_SEMAPHORE_WAIT>(semaphore, debugPauseStateAddress, DebugPauseState::hasUserStartConfirmation)) {
semaphoreBeforeWalkerFound++;
}
if (verifySemaphore<MI_SEMAPHORE_WAIT>(semaphore, debugPauseStateAddress, DebugPauseState::hasUserEndConfirmation)) {
semaphoreAfterWalkerFound++;
}
semaphore = find<MI_SEMAPHORE_WAIT *>(++semaphore, cmdList.end());
}
}
template <typename PIPE_CONTROL>
void findPipeControls(GenCmdList &cmdList) {
auto pipeControl = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
while (pipeControl != cmdList.end()) {
if (verifyPipeControl<PIPE_CONTROL>(pipeControl, debugPauseStateAddress, DebugPauseState::waitingForUserStartConfirmation)) {
pipeControlBeforeWalkerFound++;
}
if (verifyPipeControl<PIPE_CONTROL>(pipeControl, debugPauseStateAddress, DebugPauseState::waitingForUserEndConfirmation)) {
pipeControlAfterWalkerFound++;
}
pipeControl = find<PIPE_CONTROL *>(++pipeControl, cmdList.end());
}
}
DebugManagerStateRestore restore;
const size_t off[3] = {0, 0, 0};
const size_t gws[3] = {1, 1, 1};
uint64_t debugPauseStateAddress = 0;
uint32_t semaphoreBeforeWalkerFound = 0;
uint32_t semaphoreAfterWalkerFound = 0;
uint32_t pipeControlBeforeWalkerFound = 0;
uint32_t pipeControlAfterWalkerFound = 0;
};
HWTEST_F(PauseOnGpuTests, givenPauseOnEnqueueFlagSetWhenDispatchWalkersThenInsertPauseCommandsAroundSpecifiedEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
DebugManagerStateRestore restore;
DebugManager.flags.PauseOnEnqueue.set(1);
auto &csr = pDevice->getGpgpuCommandStreamReceiver();
auto debugPauseStateAddress = csr.getDebugPauseStateGPUAddress();
MockKernelWithInternals mockKernel(*pClDevice);
size_t off[3] = {0, 0, 0};
size_t gws[3] = {1, 1, 1};
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(*pCmdQ);
auto &cmdList = hwParser.cmdList;
auto semaphore = find<MI_SEMAPHORE_WAIT *>(cmdList.begin(), cmdList.end());
bool semaphoreBeforeWalkerFound = false;
bool semaphoreAfterWalkerFound = false;
while (semaphore != cmdList.end()) {
auto semaphoreCmd = genCmdCast<MI_SEMAPHORE_WAIT *>(*semaphore);
if (static_cast<uint32_t>(DebugPauseState::hasUserStartConfirmation) == semaphoreCmd->getSemaphoreDataDword()) {
EXPECT_EQ(debugPauseStateAddress, semaphoreCmd->getSemaphoreGraphicsAddress());
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_EQUAL_SDD, semaphoreCmd->getCompareOperation());
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, semaphoreCmd->getWaitMode());
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
semaphoreBeforeWalkerFound = true;
}
EXPECT_EQ(1u, semaphoreBeforeWalkerFound);
EXPECT_EQ(1u, semaphoreAfterWalkerFound);
if (static_cast<uint32_t>(DebugPauseState::hasUserEndConfirmation) == semaphoreCmd->getSemaphoreDataDword()) {
EXPECT_TRUE(semaphoreBeforeWalkerFound);
EXPECT_EQ(debugPauseStateAddress, semaphoreCmd->getSemaphoreGraphicsAddress());
EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_EQUAL_SDD, semaphoreCmd->getCompareOperation());
EXPECT_EQ(MI_SEMAPHORE_WAIT::WAIT_MODE::WAIT_MODE_POLLING_MODE, semaphoreCmd->getWaitMode());
findPipeControls<PIPE_CONTROL>(hwParser.cmdList);
semaphoreAfterWalkerFound = true;
break;
}
semaphore = find<MI_SEMAPHORE_WAIT *>(++semaphore, cmdList.end());
}
EXPECT_TRUE(semaphoreAfterWalkerFound);
auto pipeControl = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
bool pipeControlBeforeWalkerFound = false;
bool pipeControlAfterWalkerFound = false;
while (pipeControl != cmdList.end()) {
auto pipeControlCmd = genCmdCast<PIPE_CONTROL *>(*pipeControl);
if (static_cast<uint32_t>(DebugPauseState::waitingForUserStartConfirmation) == pipeControlCmd->getImmediateData()) {
EXPECT_TRUE(pipeControlCmd->getCommandStreamerStallEnable());
EXPECT_TRUE(pipeControlCmd->getDcFlushEnable());
EXPECT_EQ(static_cast<uint32_t>(debugPauseStateAddress & 0x0000FFFFFFFFULL), pipeControlCmd->getAddress());
EXPECT_EQ(static_cast<uint32_t>(debugPauseStateAddress >> 32), pipeControlCmd->getAddressHigh());
EXPECT_EQ(PIPE_CONTROL::POST_SYNC_OPERATION::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA, pipeControlCmd->getPostSyncOperation());
pipeControlBeforeWalkerFound = true;
}
if (static_cast<uint32_t>(DebugPauseState::waitingForUserEndConfirmation) == pipeControlCmd->getImmediateData()) {
EXPECT_TRUE(pipeControlBeforeWalkerFound);
EXPECT_TRUE(pipeControlCmd->getCommandStreamerStallEnable());
EXPECT_TRUE(pipeControlCmd->getDcFlushEnable());
EXPECT_EQ(static_cast<uint32_t>(debugPauseStateAddress & 0x0000FFFFFFFFULL), pipeControlCmd->getAddress());
EXPECT_EQ(static_cast<uint32_t>(debugPauseStateAddress >> 32), pipeControlCmd->getAddressHigh());
EXPECT_EQ(PIPE_CONTROL::POST_SYNC_OPERATION::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA, pipeControlCmd->getPostSyncOperation());
pipeControlAfterWalkerFound = true;
break;
}
pipeControl = find<PIPE_CONTROL *>(++pipeControl, cmdList.end());
}
EXPECT_TRUE(pipeControlAfterWalkerFound);
EXPECT_EQ(1u, pipeControlBeforeWalkerFound);
EXPECT_EQ(1u, pipeControlAfterWalkerFound);
}
HWTEST_F(EnqueueKernelTest, givenPauseOnEnqueueFlagSetWhenDispatchWalkersThenDontInsertPauseCommandsWhenUsingSpecialQueue) {
using WALKER_TYPE = typename FamilyType::WALKER_TYPE;
HWTEST_F(PauseOnGpuTests, givenPauseOnEnqueueFlagSetToMinusTwoWhenDispatchWalkersThenInsertPauseCommandsAroundEachEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
DebugManagerStateRestore restore;
DebugManager.flags.PauseOnEnqueue.set(0);
auto &csr = pDevice->getGpgpuCommandStreamReceiver();
auto debugPauseStateAddress = csr.getDebugPauseStateGPUAddress();
DebugManager.flags.PauseOnEnqueue.set(-2);
MockKernelWithInternals mockKernel(*pClDevice);
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(*pCmdQ);
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
findPipeControls<PIPE_CONTROL>(hwParser.cmdList);
EXPECT_EQ(2u, semaphoreBeforeWalkerFound);
EXPECT_EQ(2u, semaphoreAfterWalkerFound);
EXPECT_EQ(2u, pipeControlBeforeWalkerFound);
EXPECT_EQ(2u, pipeControlAfterWalkerFound);
}
HWTEST_F(PauseOnGpuTests, givenPauseModeSetToBeforeOnlyWhenDispatchingThenInsertPauseOnlyBeforeEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
DebugManager.flags.PauseOnEnqueue.set(0);
DebugManager.flags.PauseOnGpuMode.set(PauseOnGpuProperties::PauseMode::BeforeWorkload);
MockKernelWithInternals mockKernel(*pClDevice);
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(*pCmdQ);
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
findPipeControls<PIPE_CONTROL>(hwParser.cmdList);
EXPECT_EQ(1u, semaphoreBeforeWalkerFound);
EXPECT_EQ(0u, semaphoreAfterWalkerFound);
EXPECT_EQ(1u, pipeControlBeforeWalkerFound);
EXPECT_EQ(0u, pipeControlAfterWalkerFound);
}
HWTEST_F(PauseOnGpuTests, givenPauseModeSetToAfterOnlyWhenDispatchingThenInsertPauseOnlyAfterEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
DebugManager.flags.PauseOnEnqueue.set(0);
DebugManager.flags.PauseOnGpuMode.set(PauseOnGpuProperties::PauseMode::AfterWorkload);
MockKernelWithInternals mockKernel(*pClDevice);
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(*pCmdQ);
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
findPipeControls<PIPE_CONTROL>(hwParser.cmdList);
EXPECT_EQ(0u, semaphoreBeforeWalkerFound);
EXPECT_EQ(1u, semaphoreAfterWalkerFound);
EXPECT_EQ(0u, pipeControlBeforeWalkerFound);
EXPECT_EQ(1u, pipeControlAfterWalkerFound);
}
HWTEST_F(PauseOnGpuTests, givenPauseModeSetToBeforeAndAfterWhenDispatchingThenInsertPauseAroundEnqueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
DebugManager.flags.PauseOnEnqueue.set(0);
DebugManager.flags.PauseOnGpuMode.set(PauseOnGpuProperties::PauseMode::BeforeAndAfterWorkload);
MockKernelWithInternals mockKernel(*pClDevice);
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(*pCmdQ);
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
findPipeControls<PIPE_CONTROL>(hwParser.cmdList);
EXPECT_EQ(1u, semaphoreBeforeWalkerFound);
EXPECT_EQ(1u, semaphoreAfterWalkerFound);
EXPECT_EQ(1u, pipeControlBeforeWalkerFound);
EXPECT_EQ(1u, pipeControlAfterWalkerFound);
}
HWTEST_F(PauseOnGpuTests, givenPauseOnEnqueueFlagSetWhenDispatchWalkersThenDontInsertPauseCommandsWhenUsingSpecialQueue) {
using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
DebugManager.flags.PauseOnEnqueue.set(0);
pCmdQ->setIsSpecialCommandQueue(true);
MockKernelWithInternals mockKernel(*pClDevice);
size_t off[3] = {0, 0, 0};
size_t gws[3] = {1, 1, 1};
pCmdQ->enqueueKernel(mockKernel.mockKernel, 1, off, gws, nullptr, 0, nullptr, nullptr);
HardwareParse hwParser;
hwParser.parseCommands<FamilyType>(*pCmdQ);
auto &cmdList = hwParser.cmdList;
auto semaphore = find<MI_SEMAPHORE_WAIT *>(cmdList.begin(), cmdList.end());
bool semaphoreBeforeWalkerFound = false;
bool semaphoreAfterWalkerFound = false;
while (semaphore != cmdList.end()) {
auto semaphoreCmd = genCmdCast<MI_SEMAPHORE_WAIT *>(*semaphore);
if (static_cast<uint32_t>(DebugPauseState::hasUserStartConfirmation) == semaphoreCmd->getSemaphoreDataDword() &&
debugPauseStateAddress == semaphoreCmd->getSemaphoreGraphicsAddress()) {
semaphoreBeforeWalkerFound = true;
}
findSemaphores<MI_SEMAPHORE_WAIT>(hwParser.cmdList);
if (static_cast<uint32_t>(DebugPauseState::hasUserEndConfirmation) == semaphoreCmd->getSemaphoreDataDword() &&
debugPauseStateAddress == semaphoreCmd->getSemaphoreGraphicsAddress()) {
semaphoreAfterWalkerFound = true;
}
findPipeControls<PIPE_CONTROL>(hwParser.cmdList);
semaphore = find<MI_SEMAPHORE_WAIT *>(++semaphore, cmdList.end());
}
EXPECT_FALSE(semaphoreBeforeWalkerFound);
EXPECT_FALSE(semaphoreAfterWalkerFound);
auto pipeControl = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
bool pipeControlBeforeWalkerFound = false;
bool pipeControlAfterWalkerFound = false;
while (pipeControl != cmdList.end()) {
auto pipeControlCmd = genCmdCast<PIPE_CONTROL *>(*pipeControl);
if (static_cast<uint32_t>(DebugPauseState::waitingForUserStartConfirmation) == pipeControlCmd->getImmediateData()) {
pipeControlBeforeWalkerFound = true;
}
if (static_cast<uint32_t>(DebugPauseState::waitingForUserEndConfirmation) == pipeControlCmd->getImmediateData()) {
pipeControlAfterWalkerFound = true;
}
pipeControl = find<PIPE_CONTROL *>(++pipeControl, cmdList.end());
}
EXPECT_FALSE(pipeControlBeforeWalkerFound);
EXPECT_FALSE(pipeControlAfterWalkerFound);
EXPECT_EQ(0u, semaphoreBeforeWalkerFound);
EXPECT_EQ(0u, semaphoreAfterWalkerFound);
EXPECT_EQ(0u, pipeControlBeforeWalkerFound);
EXPECT_EQ(0u, pipeControlAfterWalkerFound);
pCmdQ->setIsSpecialCommandQueue(false);
}

View File

@ -194,4 +194,5 @@ EnableUsmCompression = -1
PerformImplicitFlushEveryEnqueueCount = -1
PerformImplicitFlushForNewResource = -1
PerformImplicitFlushForIdleGpu = -1
ProvideVerboseImplicitFlush = false
ProvideVerboseImplicitFlush = false
PauseOnGpuMode = -1

View File

@ -20,6 +20,7 @@
#include "shared/source/helpers/flat_batch_buffer_helper_hw.h"
#include "shared/source/helpers/flush_stamp.h"
#include "shared/source/helpers/hw_helper.h"
#include "shared/source/helpers/pause_on_gpu_properties.h"
#include "shared/source/helpers/preamble.h"
#include "shared/source/helpers/ptr_math.h"
#include "shared/source/helpers/state_base_address.h"
@ -930,15 +931,13 @@ uint32_t CommandStreamReceiverHw<GfxFamily>::blitBuffer(const BlitPropertiesCont
auto lock = obtainUniqueOwnership();
bool pauseOnBlitCopyAllowed = (DebugManager.flags.PauseOnBlitCopy.get() == static_cast<int32_t>(taskCount));
auto &commandStream = getCS(BlitCommandsHelper<GfxFamily>::estimateBlitCommandsSize(blitPropertiesContainer, profilingEnabled, pauseOnBlitCopyAllowed,
auto &commandStream = getCS(BlitCommandsHelper<GfxFamily>::estimateBlitCommandsSize(blitPropertiesContainer, profilingEnabled, PauseOnGpuProperties::featureEnabled(DebugManager.flags.PauseOnBlitCopy.get()),
*this->executionEnvironment.rootDeviceEnvironments[this->rootDeviceIndex]));
auto commandStreamStart = commandStream.getUsed();
auto newTaskCount = taskCount + 1;
latestSentTaskCount = newTaskCount;
if (pauseOnBlitCopyAllowed) {
if (PauseOnGpuProperties::pauseModeAllowed(DebugManager.flags.PauseOnBlitCopy.get(), taskCount, PauseOnGpuProperties::PauseMode::BeforeWorkload)) {
BlitCommandsHelper<GfxFamily>::dispatchDebugPauseCommands(commandStream, getDebugPauseStateGPUAddress(), DebugPauseState::waitingForUserStartConfirmation, DebugPauseState::hasUserStartConfirmation);
}
@ -983,7 +982,7 @@ uint32_t CommandStreamReceiverHw<GfxFamily>::blitBuffer(const BlitPropertiesCont
MemorySynchronizationCommands<GfxFamily>::addAdditionalSynchronization(commandStream, tagAllocation->getGpuAddress(), peekHwInfo());
if (pauseOnBlitCopyAllowed) {
if (PauseOnGpuProperties::pauseModeAllowed(DebugManager.flags.PauseOnBlitCopy.get(), taskCount, PauseOnGpuProperties::PauseMode::AfterWorkload)) {
BlitCommandsHelper<GfxFamily>::dispatchDebugPauseCommands(commandStream, getDebugPauseStateGPUAddress(), DebugPauseState::waitingForUserEndConfirmation, DebugPauseState::hasUserEndConfirmation);
}

View File

@ -65,8 +65,9 @@ DECLARE_DEBUG_VARIABLE(int32_t, OverrideGpuAddressSpace, -1, "-1: Default, !=-1:
DECLARE_DEBUG_VARIABLE(int32_t, OverrideMaxWorkgroupSize, -1, "-1: Default, !=-1: Overrides max worgkroup size to this value")
DECLARE_DEBUG_VARIABLE(int32_t, DoCpuCopyOnReadBuffer, -1, "-1: default 0: do not use CPU copy, 1: triggers CPU copy path for Read Buffer calls, only supported for some basic use cases (no blocked user events in dependencies tree)")
DECLARE_DEBUG_VARIABLE(int32_t, DoCpuCopyOnWriteBuffer, -1, "-1: default 0: do not use CPU copy, 1: triggers CPU copy path for Write Buffer calls, only supported for some basic use cases (no blocked user events in dependencies tree)")
DECLARE_DEBUG_VARIABLE(int32_t, PauseOnEnqueue, -1, "-1: default, x: pause on enqueue number x and ask for user confirmation before and after execution, counted from 0")
DECLARE_DEBUG_VARIABLE(int32_t, PauseOnBlitCopy, -1, "-1: default, x: pause on blit enqueue number x and ask for user confirmation before and after execution, counted from 0. Note that single blit enqueue may have multiple copy instructions")
DECLARE_DEBUG_VARIABLE(int32_t, PauseOnEnqueue, -1, "-1: default, -2: always, x: pause on enqueue number x and ask for user confirmation before and after execution, counted from 0")
DECLARE_DEBUG_VARIABLE(int32_t, PauseOnBlitCopy, -1, "-1: default, -2: always, x: pause on blit enqueue number x and ask for user confirmation before and after execution, counted from 0. Note that single blit enqueue may have multiple copy instructions")
DECLARE_DEBUG_VARIABLE(int32_t, PauseOnGpuMode, -1, "-1: default (before and after), 0: before only, 1: after only")
DECLARE_DEBUG_VARIABLE(int32_t, EnableMultiStorageResources, -1, "-1: default, 0: Disable, 1: Enable")
DECLARE_DEBUG_VARIABLE(int32_t, LimitBlitterMaxWidth, -1, "-1: default, >=0: Max width")
DECLARE_DEBUG_VARIABLE(int32_t, LimitBlitterMaxHeight, -1, "-1: default, >=0: Max height")

View File

@ -64,6 +64,7 @@ set(NEO_CORE_HELPERS
${CMAKE_CURRENT_SOURCE_DIR}/kmd_notify_properties.h
${CMAKE_CURRENT_SOURCE_DIR}/non_copyable_or_moveable.h
${CMAKE_CURRENT_SOURCE_DIR}/options.h
${CMAKE_CURRENT_SOURCE_DIR}/pause_on_gpu_properties.h
${CMAKE_CURRENT_SOURCE_DIR}/pipeline_select_args.h
${CMAKE_CURRENT_SOURCE_DIR}/pipeline_select_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/preamble.h

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/debug_settings/debug_settings_manager.h"
#include <cstdint>
namespace NEO {
namespace PauseOnGpuProperties {
enum PauseMode : int32_t {
BeforeAndAfterWorkload = -1,
BeforeWorkload = 0,
AfterWorkload = 1
};
enum DebugFlagValues : int32_t {
OnEachEnqueue = -2,
Disabled = -1
};
inline bool featureEnabled(int32_t debugFlagValue) {
return (debugFlagValue != DebugFlagValues::Disabled);
}
inline bool pauseModeAllowed(int32_t debugFlagValue, uint32_t taskCount, PauseMode pauseMode) {
if (!featureEnabled(debugFlagValue)) {
// feature disabled
return false;
}
if ((DebugManager.flags.PauseOnGpuMode.get() != PauseMode::BeforeAndAfterWorkload) && (DebugManager.flags.PauseOnGpuMode.get() != pauseMode)) {
// mode not allowed
return false;
}
if (debugFlagValue == DebugFlagValues::OnEachEnqueue) {
// pause on each enqueue
return true;
}
return (debugFlagValue == static_cast<int32_t>(taskCount));
}
} // namespace PauseOnGpuProperties
} // namespace NEO