Fix heap programming in blocked scenarios.

- When command queue is blocked, all heaps are being stored in temporary
allocations, command buffers are being pre-programmed, heaps are being set
on those temporary allocations with the assumption that all heaps start with
offset 0.
- Problem was when the actual submissions happened, all those temporary heaps
were just copied to appended command queue heaps, so when something was there
then new stuff was copied right after it. It means that all state was
incorrect as the offsets are not valid anymore and will point to wrong
location.

- This change releases command queue heaps when blocked command is being
submitted to make sure they will be programmed with the proper offset in newly
allocate command queue heap.

Change-Id: I3e30be13caf4df8621ddb18f8448ffaf0f1278d1
This commit is contained in:
Mrozek, Michal 2018-01-04 10:39:51 +01:00
parent a8b91c8c99
commit 57137fea84
2 changed files with 71 additions and 3 deletions

View File

@ -151,6 +151,14 @@ CompletionStamp &CommandComputeKernel::submit(uint32_t taskLevel, bool terminate
IndirectHeap *dsh = nullptr;
IndirectHeap *ioh = nullptr;
IndirectHeap::Type trackedHeaps[] = {IndirectHeap::SURFACE_STATE, IndirectHeap::INDIRECT_OBJECT, IndirectHeap::DYNAMIC_STATE, IndirectHeap::INSTRUCTION};
for (auto trackedHeap = 0u; trackedHeap < ARRAY_COUNT(trackedHeaps); trackedHeap++) {
if (commandQueue.getIndirectHeap(trackedHeaps[trackedHeap], 0).getUsed() > 0) {
commandQueue.releaseIndirectHeap(trackedHeaps[trackedHeap]);
}
}
if (executionModelKernel) {
dsh = devQueue->getIndirectHeap(IndirectHeap::DYNAMIC_STATE);
// In ExecutionModel IOH is the same as DSH to eliminate StateBaseAddress reprogramming for scheduler kernel and blocks.
@ -158,9 +166,6 @@ CompletionStamp &CommandComputeKernel::submit(uint32_t taskLevel, bool terminate
memcpy_s(dsh->getSpace(0), dsh->getAvailableSpace(), ptrOffset(kernelOperation->dsh->getBase(), devQueue->colorCalcStateSize), kernelOperation->dsh->getUsed() - devQueue->colorCalcStateSize);
dsh->getSpace(kernelOperation->dsh->getUsed() - devQueue->colorCalcStateSize);
if (commandQueue.getIndirectHeap(IndirectHeap::SURFACE_STATE, 0).getUsed() > 0)
commandQueue.releaseIndirectHeap(IndirectHeap::SURFACE_STATE);
} else {
dsh = &commandQueue.getIndirectHeap(IndirectHeap::DYNAMIC_STATE, requestedDshSize);
ioh = &commandQueue.getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, requestedIohSize);

View File

@ -348,6 +348,69 @@ HWTEST_F(CommandQueueHwTest, GivenNotCompleteUserEventPassedToEnqueueWhenEventIs
mockCSR->getMemoryManager()->freeGraphicsMemory(printfSurface);
mockCSR->getMemoryManager()->freeGraphicsMemory(constantSurface);
}
typedef CommandQueueHwTest BlockedCommandQueueTest;
HWTEST_F(BlockedCommandQueueTest, givenCommandQueueWhichHasSomeUsedHeapsWhenBlockedCommandIsBeingSubmittedItReloadsThemToZeroToKeepProperOffsets) {
UserEvent userEvent(context);
MockKernelWithInternals mockKernelWithInternals(*pDevice);
auto mockKernel = mockKernelWithInternals.mockKernel;
size_t offset = 0;
size_t size = 1;
cl_event blockedEvent = &userEvent;
auto &ish = pCmdQ->getIndirectHeap(IndirectHeap::INSTRUCTION, 4096u);
auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 4096u);
auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 4096u);
auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 4096u);
ssh.getSpace(1);
ish.getSpace(1);
ioh.getSpace(1);
dsh.getSpace(1);
auto ishBase = ish.getBase();
auto iohBase = ioh.getBase();
auto dshBase = dsh.getBase();
auto sshBase = ssh.getBase();
pCmdQ->enqueueKernel(mockKernel, 1, &offset, &size, &size, 1, &blockedEvent, nullptr);
userEvent.setStatus(CL_COMPLETE);
EXPECT_NE(ishBase, ish.getBase());
EXPECT_NE(iohBase, ioh.getBase());
EXPECT_NE(dshBase, dsh.getBase());
EXPECT_NE(sshBase, ssh.getBase());
}
HWTEST_F(BlockedCommandQueueTest, givenCommandQueueWhichHasSomeUnusedHeapsWhenBlockedCommandIsBeingSubmittedThenThoseHeapsAreBeingUsed) {
UserEvent userEvent(context);
MockKernelWithInternals mockKernelWithInternals(*pDevice);
auto mockKernel = mockKernelWithInternals.mockKernel;
size_t offset = 0;
size_t size = 1;
cl_event blockedEvent = &userEvent;
auto &ish = pCmdQ->getIndirectHeap(IndirectHeap::INSTRUCTION, 4096u);
auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 4096u);
auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 4096u);
auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 4096u);
auto ishBase = ish.getBase();
auto iohBase = ioh.getBase();
auto dshBase = dsh.getBase();
auto sshBase = ssh.getBase();
pCmdQ->enqueueKernel(mockKernel, 1, &offset, &size, &size, 1, &blockedEvent, nullptr);
userEvent.setStatus(CL_COMPLETE);
EXPECT_EQ(ishBase, ish.getBase());
EXPECT_EQ(iohBase, ioh.getBase());
EXPECT_EQ(dshBase, dsh.getBase());
EXPECT_EQ(sshBase, ssh.getBase());
}
typedef CommandQueueHwTest CommandQueueHwRefCountTest;