@@ -160,6 +160,57 @@ HWTEST_F(PrintfHandlerTests, givenEnabledStatelessCompressionWhenPrintEnqueueOut
160160 }
161161}
162162
163+ HWTEST_F (PrintfHandlerTests, givenDisallowedLocalMemoryCpuAccessWhenPrintEnqueueOutputIsCalledThenBCSEngineIsUsedToCopyPrintfOutput) {
164+ HardwareInfo hwInfo = *defaultHwInfo;
165+ hwInfo.capabilityTable .blitterOperationsSupported = true ;
166+ REQUIRE_BLITTER_OR_SKIP (&hwInfo);
167+
168+ class MockPrintfHandler : public PrintfHandler {
169+ public:
170+ using PrintfHandler::PrintfHandler;
171+ using PrintfHandler::printfSurface;
172+
173+ MockPrintfHandler (ClDevice &device) : PrintfHandler(device) {}
174+ };
175+
176+ DebugManagerStateRestore restore;
177+ DebugManager.flags .ForceLocalMemoryAccessMode .set (static_cast <int32_t >(LocalMemoryAccessMode::CpuAccessDisallowed));
178+ DebugManager.flags .EnableLocalMemory .set (1 );
179+
180+ auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(&hwInfo));
181+ MockContext context (device.get ());
182+
183+ auto kernelInfo = std::make_unique<MockKernelInfo>();
184+ kernelInfo->setPrintfSurface (sizeof (uintptr_t ), 0 );
185+
186+ auto program = std::make_unique<MockProgram>(&context, false , toClDeviceVector (*device));
187+
188+ uint64_t crossThread[10 ]{};
189+ auto kernel = std::make_unique<MockKernel>(program.get (), *kernelInfo, *device);
190+ kernel->setCrossThreadData (&crossThread, sizeof (uint64_t ) * 8 );
191+
192+ MockMultiDispatchInfo multiDispatchInfo (device.get (), kernel.get ());
193+ auto printfHandler = std::make_unique<MockPrintfHandler>(*device);
194+
195+ printfHandler->prepareDispatch (multiDispatchInfo);
196+ EXPECT_NE (nullptr , printfHandler->getSurface ());
197+
198+ device->getMemoryManager ()->freeGraphicsMemory (printfHandler->printfSurface );
199+
200+ auto allocation = new MockGraphicsAllocation (reinterpret_cast <void *>(0x1000 ), 0x1000 );
201+ allocation->memoryPool = MemoryPool::LocalMemory;
202+
203+ printfHandler->printfSurface = allocation;
204+
205+ printfHandler->printEnqueueOutput ();
206+
207+ auto &bcsEngine = device->getEngine (EngineHelpers::getBcsEngineType (device->getHardwareInfo (), device->getDeviceBitfield (), device->getSelectorCopyEngine (), true ), EngineUsage::Regular);
208+ auto bcsCsr = static_cast <UltCommandStreamReceiver<FamilyType> *>(bcsEngine.commandStreamReceiver );
209+
210+ EXPECT_TRUE (bcsCsr->blitBufferCalled >= 1 );
211+ EXPECT_EQ (BlitterConstants::BlitDirection::BufferToHostPtr, bcsCsr->receivedBlitProperties [0 ].blitDirection );
212+ }
213+
163214HWTEST_F (PrintfHandlerTests, givenPrintfHandlerWhenEnqueueIsBlockedThenDontUsePrintfObjectAfterMove) {
164215 DebugManagerStateRestore restore;
165216 DebugManager.flags .MakeEachEnqueueBlocking .set (true );
0 commit comments