fix: don't override user data during staging read
Related-To: NEO-13574 User can read image with row pitch larger than region width. In such cases, don't override memory which is out of region but within row pitch. Signed-off-by: Szymon Morek <szymon.morek@intel.com>
This commit is contained in:
parent
e82ee0fd70
commit
8152241693
|
@ -70,7 +70,7 @@ cl_int CommandQueue::enqueueStagingImageTransfer(cl_command_type commandType, Im
|
|||
auto dstRowPitch = inputRowPitch ? inputRowPitch : globalRegion[0] * bytesPerPixel;
|
||||
|
||||
auto stagingBufferManager = this->context->getStagingBufferManager();
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, dstRowPitch, chunkWrite, &csr, isRead);
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, dstRowPitch, bytesPerPixel, chunkWrite, &csr, isRead);
|
||||
return postStagingTransferSync(ret, event, profilingEvent, isSingleTransfer, blockingCopy, commandType);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,31 +55,31 @@ StagingBufferManager::~StagingBufferManager() {
|
|||
* or tracking container for further reusage.
|
||||
*/
|
||||
template <class Func, class... Args>
|
||||
StagingTransferStatus StagingBufferManager::performChunkTransfer(bool isRead, void *userPtr, size_t size, StagingQueue ¤tStagingBuffers, CommandStreamReceiver *csr, Func &func, Args... args) {
|
||||
StagingTransferStatus StagingBufferManager::performChunkTransfer(size_t chunkTransferId, bool isRead, const UserData &userData, StagingQueue ¤tStagingBuffers, CommandStreamReceiver *csr, Func &func, Args... args) {
|
||||
StagingTransferStatus result{};
|
||||
StagingBufferTracker tracker{};
|
||||
if (currentStagingBuffers.size() > 1) {
|
||||
if (fetchHead(currentStagingBuffers, tracker) == WaitStatus::gpuHang) {
|
||||
auto stagingBufferIndex = chunkTransferId % maxInFlightReads;
|
||||
if (isRead && chunkTransferId >= maxInFlightReads) {
|
||||
if (copyStagingToHost(currentStagingBuffers[stagingBufferIndex], tracker) == WaitStatus::gpuHang) {
|
||||
result.waitStatus = WaitStatus::gpuHang;
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
auto allocatedSize = size;
|
||||
auto allocatedSize = userData.size;
|
||||
auto [allocator, stagingBuffer] = requestStagingBuffer(allocatedSize);
|
||||
tracker = StagingBufferTracker{allocator, stagingBuffer, allocatedSize, csr};
|
||||
}
|
||||
|
||||
auto stagingBuffer = addrToPtr(tracker.chunkAddress);
|
||||
if (!isRead) {
|
||||
memcpy(stagingBuffer, userPtr, size);
|
||||
memcpy(stagingBuffer, userData.ptr, userData.size);
|
||||
}
|
||||
|
||||
result.chunkCopyStatus = func(stagingBuffer, args...);
|
||||
|
||||
tracker.taskCountToWait = csr->peekTaskCount();
|
||||
if (isRead) {
|
||||
UserDstData dstData{userPtr, size};
|
||||
currentStagingBuffers.push({dstData, tracker});
|
||||
currentStagingBuffers[stagingBufferIndex] = {userData, tracker};
|
||||
} else {
|
||||
trackChunk(tracker);
|
||||
}
|
||||
|
@ -103,7 +103,8 @@ StagingTransferStatus StagingBufferManager::performCopy(void *dstPtr, const void
|
|||
for (auto i = 0u; i < copiesNum; i++) {
|
||||
auto chunkDst = ptrOffset(dstPtr, i * chunkSize);
|
||||
auto chunkSrc = ptrOffset(srcPtr, i * chunkSize);
|
||||
result = performChunkTransfer(false, const_cast<void *>(chunkSrc), chunkSize, stagingQueue, csr, chunkCopyFunc, chunkDst, chunkSize);
|
||||
UserData userData{chunkSrc, chunkSize};
|
||||
result = performChunkTransfer(i, false, userData, stagingQueue, csr, chunkCopyFunc, chunkDst, chunkSize);
|
||||
if (result.chunkCopyStatus != 0) {
|
||||
return result;
|
||||
}
|
||||
|
@ -112,7 +113,8 @@ StagingTransferStatus StagingBufferManager::performCopy(void *dstPtr, const void
|
|||
if (remainder != 0) {
|
||||
auto chunkDst = ptrOffset(dstPtr, copiesNum * chunkSize);
|
||||
auto chunkSrc = ptrOffset(srcPtr, copiesNum * chunkSize);
|
||||
auto result = performChunkTransfer(false, const_cast<void *>(chunkSrc), remainder, stagingQueue, csr, chunkCopyFunc, chunkDst, remainder);
|
||||
UserData userData{chunkSrc, remainder};
|
||||
auto result = performChunkTransfer(copiesNum, false, userData, stagingQueue, csr, chunkCopyFunc, chunkDst, remainder);
|
||||
if (result.chunkCopyStatus != 0) {
|
||||
return result;
|
||||
}
|
||||
|
@ -127,7 +129,7 @@ StagingTransferStatus StagingBufferManager::performCopy(void *dstPtr, const void
|
|||
* Several rows are packed into single chunk unless size of single row exceeds maximum chunk size (2MB).
|
||||
* Caller provides actual function to enqueue read/write operation for single chunk.
|
||||
*/
|
||||
StagingTransferStatus StagingBufferManager::performImageTransfer(const void *ptr, const size_t *globalOrigin, const size_t *globalRegion, size_t rowPitch, ChunkTransferImageFunc &chunkTransferImageFunc, CommandStreamReceiver *csr, bool isRead) {
|
||||
StagingTransferStatus StagingBufferManager::performImageTransfer(const void *ptr, const size_t *globalOrigin, const size_t *globalRegion, size_t rowPitch, size_t bytesPerPixel, ChunkTransferImageFunc &chunkTransferImageFunc, CommandStreamReceiver *csr, bool isRead) {
|
||||
StagingQueue stagingQueue;
|
||||
size_t origin[3] = {};
|
||||
size_t region[3] = {};
|
||||
|
@ -140,13 +142,16 @@ StagingTransferStatus StagingBufferManager::performImageTransfer(const void *ptr
|
|||
auto numOfChunks = globalRegion[1] / rowsPerChunk;
|
||||
auto remainder = globalRegion[1] % (rowsPerChunk * numOfChunks);
|
||||
StagingTransferStatus result{};
|
||||
RowPitchData rowPitchData{region[0] * bytesPerPixel, rowPitch, rowsPerChunk};
|
||||
|
||||
for (auto i = 0u; i < numOfChunks; i++) {
|
||||
origin[1] = globalOrigin[1] + i * rowsPerChunk;
|
||||
region[1] = rowsPerChunk;
|
||||
auto size = region[1] * rowPitch;
|
||||
auto chunkPtr = ptrOffset(ptr, i * rowsPerChunk * rowPitch);
|
||||
result = performChunkTransfer(isRead, const_cast<void *>(chunkPtr), size, stagingQueue, csr, chunkTransferImageFunc, origin, region);
|
||||
UserData userData{chunkPtr, size, rowPitchData};
|
||||
|
||||
result = performChunkTransfer(i, isRead, userData, stagingQueue, csr, chunkTransferImageFunc, origin, region);
|
||||
if (result.chunkCopyStatus != 0 || result.waitStatus == WaitStatus::gpuHang) {
|
||||
return result;
|
||||
}
|
||||
|
@ -157,13 +162,19 @@ StagingTransferStatus StagingBufferManager::performImageTransfer(const void *ptr
|
|||
region[1] = remainder;
|
||||
auto size = region[1] * rowPitch;
|
||||
auto chunkPtr = ptrOffset(ptr, numOfChunks * rowsPerChunk * rowPitch);
|
||||
result = performChunkTransfer(isRead, const_cast<void *>(chunkPtr), size, stagingQueue, csr, chunkTransferImageFunc, origin, region);
|
||||
rowPitchData.rowsInChunk = remainder;
|
||||
UserData userData{chunkPtr, size, rowPitchData};
|
||||
|
||||
result = performChunkTransfer(numOfChunks, isRead, userData, stagingQueue, csr, chunkTransferImageFunc, origin, region);
|
||||
if (result.chunkCopyStatus != 0 || result.waitStatus == WaitStatus::gpuHang) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.waitStatus = drainAndReleaseStagingQueue(stagingQueue);
|
||||
if (isRead) {
|
||||
auto numOfSubmittedTransfers = numOfChunks + (remainder != 0 ? 1 : 0);
|
||||
result.waitStatus = drainAndReleaseStagingQueue(stagingQueue, std::min(numOfSubmittedTransfers, maxInFlightReads));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -175,7 +186,8 @@ StagingTransferStatus StagingBufferManager::performBufferTransfer(const void *pt
|
|||
StagingTransferStatus result{};
|
||||
for (auto i = 0u; i < copiesNum; i++) {
|
||||
auto chunkPtr = ptrOffset(ptr, i * chunkSize);
|
||||
result = performChunkTransfer(isRead, const_cast<void *>(chunkPtr), chunkSize, stagingQueue, csr, chunkTransferBufferFunc, chunkOffset, chunkSize);
|
||||
UserData userData{chunkPtr, chunkSize};
|
||||
result = performChunkTransfer(i, isRead, userData, stagingQueue, csr, chunkTransferBufferFunc, chunkOffset, chunkSize);
|
||||
if (result.chunkCopyStatus != 0) {
|
||||
return result;
|
||||
}
|
||||
|
@ -184,33 +196,39 @@ StagingTransferStatus StagingBufferManager::performBufferTransfer(const void *pt
|
|||
|
||||
if (remainder != 0) {
|
||||
auto chunkPtr = ptrOffset(ptr, copiesNum * chunkSize);
|
||||
result = performChunkTransfer(isRead, const_cast<void *>(chunkPtr), remainder, stagingQueue, csr, chunkTransferBufferFunc, chunkOffset, remainder);
|
||||
UserData userData{chunkPtr, remainder};
|
||||
result = performChunkTransfer(copiesNum, isRead, userData, stagingQueue, csr, chunkTransferBufferFunc, chunkOffset, remainder);
|
||||
if (result.chunkCopyStatus != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.waitStatus = drainAndReleaseStagingQueue(stagingQueue);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is used for read transfers. It waits for oldest transfer to finish
|
||||
* This method is used for read transfers. It waits for transfer to finish
|
||||
* and copies data associated with that transfer to host allocation.
|
||||
* Returned tracker contains staging buffer ready for reuse.
|
||||
*/
|
||||
WaitStatus StagingBufferManager::fetchHead(StagingQueue &stagingQueue, StagingBufferTracker &tracker) const {
|
||||
auto &head = stagingQueue.front();
|
||||
auto status = head.second.csr->waitForTaskCount(head.second.taskCountToWait);
|
||||
WaitStatus StagingBufferManager::copyStagingToHost(const std::pair<UserData, StagingBufferTracker> &transfer, StagingBufferTracker &tracker) const {
|
||||
auto status = transfer.second.csr->waitForTaskCount(transfer.second.taskCountToWait);
|
||||
if (status == WaitStatus::gpuHang) {
|
||||
return status;
|
||||
}
|
||||
|
||||
auto &userData = head.first;
|
||||
tracker = head.second;
|
||||
auto &userData = transfer.first;
|
||||
tracker = transfer.second;
|
||||
auto stagingBuffer = addrToPtr(tracker.chunkAddress);
|
||||
memcpy(userData.ptr, stagingBuffer, userData.size);
|
||||
stagingQueue.pop();
|
||||
auto userDst = const_cast<void *>(userData.ptr);
|
||||
if (userData.rowPitchData.rowSize < userData.rowPitchData.rowPitch) {
|
||||
for (auto rowId = 0u; rowId < userData.rowPitchData.rowsInChunk; rowId++) {
|
||||
auto offset = rowId * userData.rowPitchData.rowPitch;
|
||||
memcpy(ptrOffset(userDst, offset), ptrOffset(stagingBuffer, offset), userData.rowPitchData.rowSize);
|
||||
}
|
||||
} else {
|
||||
memcpy(userDst, stagingBuffer, userData.size);
|
||||
}
|
||||
return WaitStatus::ready;
|
||||
}
|
||||
|
||||
|
@ -218,10 +236,10 @@ WaitStatus StagingBufferManager::fetchHead(StagingQueue &stagingQueue, StagingBu
|
|||
* Waits for all pending transfers to finish.
|
||||
* Releases staging buffers back to pool for reuse.
|
||||
*/
|
||||
WaitStatus StagingBufferManager::drainAndReleaseStagingQueue(StagingQueue &stagingQueue) const {
|
||||
WaitStatus StagingBufferManager::drainAndReleaseStagingQueue(const StagingQueue &stagingQueue, size_t numOfTransfers) const {
|
||||
StagingBufferTracker tracker{};
|
||||
while (!stagingQueue.empty()) {
|
||||
auto status = fetchHead(stagingQueue, tracker);
|
||||
for (auto i = 0u; i < numOfTransfers; i++) {
|
||||
auto status = copyStagingToHost(stagingQueue[i], tracker);
|
||||
if (status == WaitStatus::gpuHang) {
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -58,9 +58,16 @@ struct StagingBufferTracker {
|
|||
void freeChunk() const;
|
||||
};
|
||||
|
||||
struct UserDstData {
|
||||
void *ptr;
|
||||
size_t size;
|
||||
struct RowPitchData {
|
||||
size_t rowSize = 0;
|
||||
size_t rowPitch = 0;
|
||||
size_t rowsInChunk = 0;
|
||||
};
|
||||
|
||||
struct UserData {
|
||||
const void *ptr = nullptr;
|
||||
size_t size = 0;
|
||||
RowPitchData rowPitchData{};
|
||||
};
|
||||
|
||||
struct StagingTransferStatus {
|
||||
|
@ -68,7 +75,8 @@ struct StagingTransferStatus {
|
|||
WaitStatus waitStatus = WaitStatus::ready;
|
||||
};
|
||||
|
||||
using StagingQueue = std::queue<std::pair<UserDstData, StagingBufferTracker>>;
|
||||
constexpr size_t maxInFlightReads = 2u;
|
||||
using StagingQueue = StackVec<std::pair<UserData, StagingBufferTracker>, maxInFlightReads>;
|
||||
|
||||
class StagingBufferManager {
|
||||
public:
|
||||
|
@ -83,7 +91,7 @@ class StagingBufferManager {
|
|||
bool isValidForStagingTransfer(const Device &device, const void *ptr, size_t size, bool hasDependencies);
|
||||
|
||||
StagingTransferStatus performCopy(void *dstPtr, const void *srcPtr, size_t size, ChunkCopyFunction &chunkCopyFunc, CommandStreamReceiver *csr);
|
||||
StagingTransferStatus performImageTransfer(const void *ptr, const size_t *globalOrigin, const size_t *globalRegion, size_t rowPitch, ChunkTransferImageFunc &chunkTransferImageFunc, CommandStreamReceiver *csr, bool isRead);
|
||||
StagingTransferStatus performImageTransfer(const void *ptr, const size_t *globalOrigin, const size_t *globalRegion, size_t rowPitch, size_t bytesPerPixel, ChunkTransferImageFunc &chunkTransferImageFunc, CommandStreamReceiver *csr, bool isRead);
|
||||
StagingTransferStatus performBufferTransfer(const void *ptr, size_t globalOffset, size_t globalSize, ChunkTransferBufferFunc &chunkTransferBufferFunc, CommandStreamReceiver *csr, bool isRead);
|
||||
|
||||
std::pair<HeapAllocator *, uint64_t> requestStagingBuffer(size_t &size);
|
||||
|
@ -98,10 +106,10 @@ class StagingBufferManager {
|
|||
void clearTrackedChunks();
|
||||
|
||||
template <class Func, class... Args>
|
||||
StagingTransferStatus performChunkTransfer(bool isRead, void *userPtr, size_t size, StagingQueue ¤tStagingBuffers, CommandStreamReceiver *csr, Func &func, Args... args);
|
||||
StagingTransferStatus performChunkTransfer(size_t chunkTransferId, bool isRead, const UserData &userData, StagingQueue ¤tStagingBuffers, CommandStreamReceiver *csr, Func &func, Args... args);
|
||||
|
||||
WaitStatus fetchHead(StagingQueue &stagingQueue, StagingBufferTracker &tracker) const;
|
||||
WaitStatus drainAndReleaseStagingQueue(StagingQueue &stagingQueue) const;
|
||||
WaitStatus copyStagingToHost(const std::pair<UserData, StagingBufferTracker> &transfer, StagingBufferTracker &tracker) const;
|
||||
WaitStatus drainAndReleaseStagingQueue(const StagingQueue &stagingQueue, size_t numOfTransfers) const;
|
||||
|
||||
bool isValidForStaging(const Device &device, const void *ptr, size_t size, bool hasDependencies);
|
||||
|
||||
|
|
|
@ -85,20 +85,26 @@ class StagingBufferManagerFixture : public DeviceFixture {
|
|||
}
|
||||
|
||||
void imageTransferThroughStagingBuffers(bool isRead, size_t rowPitch, const size_t *globalOrigin, const size_t *globalRegion, size_t expectedChunks) {
|
||||
auto hostPtr = new unsigned char[stagingBufferSize * expectedChunks];
|
||||
auto imageData = new unsigned char[stagingBufferSize * expectedChunks];
|
||||
auto hostPtr = new unsigned char[stagingBufferSize * (expectedChunks + globalOrigin[1])];
|
||||
auto imageData = new unsigned char[stagingBufferSize * (expectedChunks + globalOrigin[1])];
|
||||
if (isRead) {
|
||||
memset(hostPtr, 0, stagingBufferSize * expectedChunks);
|
||||
memset(imageData, 0xFF, stagingBufferSize * expectedChunks);
|
||||
memset(hostPtr, 0, stagingBufferSize * (expectedChunks + globalOrigin[1]));
|
||||
memset(imageData, 0xFF, stagingBufferSize * (expectedChunks + globalOrigin[1]));
|
||||
} else {
|
||||
memset(hostPtr, 0xFF, stagingBufferSize * expectedChunks);
|
||||
memset(imageData, 0, stagingBufferSize * expectedChunks);
|
||||
memset(hostPtr, 0xFF, stagingBufferSize * (expectedChunks + globalOrigin[1]));
|
||||
memset(imageData, 0, stagingBufferSize * (expectedChunks + globalOrigin[1]));
|
||||
}
|
||||
size_t chunkCounter = 0;
|
||||
size_t expectedOrigin = globalOrigin[1];
|
||||
auto rowSize = globalRegion[0] * pixelElemSize;
|
||||
auto expectedRowsPerChunk = std::min<size_t>(std::max<size_t>(1ul, stagingBufferSize / rowPitch), globalRegion[1]);
|
||||
auto numOfChunks = globalRegion[1] / expectedRowsPerChunk;
|
||||
auto remainder = globalRegion[1] % (expectedRowsPerChunk * numOfChunks);
|
||||
|
||||
// This lambda function simulates chunk read/write on image.
|
||||
// Iterates over rows in given image chunk, copies each row with offset origin[0]
|
||||
// For writes, data is transferred in staging buffer -> image direction.
|
||||
// For reads, it's image -> staging buffer.
|
||||
ChunkTransferImageFunc chunkTransfer = [&](void *stagingBuffer, const size_t *origin, const size_t *region) -> int32_t {
|
||||
EXPECT_NE(nullptr, stagingBuffer);
|
||||
EXPECT_NE(nullptr, origin);
|
||||
|
@ -113,11 +119,14 @@ class StagingBufferManagerFixture : public DeviceFixture {
|
|||
} else {
|
||||
EXPECT_EQ(expectedRowsPerChunk, region[1]);
|
||||
}
|
||||
auto offset = origin[1] - globalOrigin[1];
|
||||
if (isRead) {
|
||||
memcpy(stagingBuffer, imageData + rowPitch * offset, rowPitch * region[1]);
|
||||
} else {
|
||||
memcpy(imageData + rowPitch * offset, stagingBuffer, rowPitch * region[1]);
|
||||
|
||||
for (auto rowId = 0u; rowId < region[1]; rowId++) {
|
||||
void *dst = ptrOffset(imageData, (origin[1] + rowId) * rowPitch + origin[0] * pixelElemSize);
|
||||
void *src = ptrOffset(stagingBuffer, rowId * rowPitch);
|
||||
if (isRead) {
|
||||
std::swap(dst, src);
|
||||
}
|
||||
memcpy(dst, src, rowSize);
|
||||
}
|
||||
expectedOrigin += region[1];
|
||||
chunkCounter++;
|
||||
|
@ -125,10 +134,14 @@ class StagingBufferManagerFixture : public DeviceFixture {
|
|||
return 0;
|
||||
};
|
||||
auto initialNumOfUsmAllocations = svmAllocsManager->svmAllocs.getNumAllocs();
|
||||
auto ret = stagingBufferManager->performImageTransfer(hostPtr, globalOrigin, globalRegion, rowPitch, chunkTransfer, csr, isRead);
|
||||
auto ret = stagingBufferManager->performImageTransfer(hostPtr, globalOrigin, globalRegion, rowPitch, pixelElemSize, chunkTransfer, csr, isRead);
|
||||
auto newUsmAllocations = svmAllocsManager->svmAllocs.getNumAllocs() - initialNumOfUsmAllocations;
|
||||
|
||||
EXPECT_EQ(0, memcmp(hostPtr, imageData, rowPitch * (numOfChunks * expectedRowsPerChunk + remainder)));
|
||||
for (auto rowId = 0u; rowId < globalRegion[1]; rowId++) {
|
||||
auto offset = (globalOrigin[1] + rowId) * rowPitch;
|
||||
EXPECT_EQ(0, memcmp(ptrOffset(hostPtr, rowId * rowPitch), ptrOffset(imageData, offset + globalOrigin[0] * pixelElemSize), rowSize));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, ret.chunkCopyStatus);
|
||||
EXPECT_EQ(WaitStatus::ready, ret.waitStatus);
|
||||
EXPECT_EQ(expectedChunks, chunkCounter);
|
||||
|
@ -171,6 +184,7 @@ class StagingBufferManagerFixture : public DeviceFixture {
|
|||
}
|
||||
|
||||
constexpr static size_t stagingBufferSize = MemoryConstants::megaByte * 2;
|
||||
constexpr static size_t pixelElemSize = 1u;
|
||||
DebugManagerStateRestore restorer;
|
||||
std::unique_ptr<MockSVMAllocsManager> svmAllocsManager;
|
||||
std::unique_ptr<StagingBufferManager> stagingBufferManager;
|
||||
|
@ -500,13 +514,20 @@ TEST_F(StagingBufferManagerTest, givenStagingBufferWhenPerformImageWriteWithRema
|
|||
imageTransferThroughStagingBuffers(false, MemoryConstants::megaByte, globalOrigin, globalRegion, expectedChunks);
|
||||
}
|
||||
|
||||
TEST_F(StagingBufferManagerTest, givenStagingBufferWhenPerformImageReadThenWholeRegionCovered) {
|
||||
TEST_F(StagingBufferManagerTest, givenStagingBufferWhenPerformImageReadThenRegionCovered) {
|
||||
size_t expectedChunks = 8;
|
||||
const size_t globalOrigin[3] = {0, 0, 0};
|
||||
const size_t globalRegion[3] = {4, expectedChunks, 1};
|
||||
imageTransferThroughStagingBuffers(true, stagingBufferSize, globalOrigin, globalRegion, expectedChunks);
|
||||
}
|
||||
|
||||
TEST_F(StagingBufferManagerTest, givenStagingBufferWhenPerformImageReadThenWholeRegionCovered) {
|
||||
size_t expectedChunks = 8;
|
||||
const size_t globalOrigin[3] = {0, 0, 0};
|
||||
const size_t globalRegion[3] = {stagingBufferSize, expectedChunks, 1};
|
||||
imageTransferThroughStagingBuffers(true, stagingBufferSize, globalOrigin, globalRegion, expectedChunks);
|
||||
}
|
||||
|
||||
TEST_F(StagingBufferManagerTest, givenStagingBufferWhenPerformImageReadWithOriginThenWholeRegionCovered) {
|
||||
size_t expectedChunks = 8;
|
||||
const size_t globalOrigin[3] = {4, 4, 0};
|
||||
|
@ -528,6 +549,13 @@ TEST_F(StagingBufferManagerTest, givenStagingBufferWhenPerformImageReadWithRemai
|
|||
imageTransferThroughStagingBuffers(true, MemoryConstants::megaByte, globalOrigin, globalRegion, expectedChunks);
|
||||
}
|
||||
|
||||
TEST_F(StagingBufferManagerTest, givenStagingBufferWhenPerformImageReadWithRemainderAndTransfersWithinLimitThenWholeRegionCovered) {
|
||||
size_t expectedChunks = 2;
|
||||
const size_t globalOrigin[3] = {0, 0, 0};
|
||||
const size_t globalRegion[3] = {4, 3, 1};
|
||||
imageTransferThroughStagingBuffers(true, MemoryConstants::megaByte, globalOrigin, globalRegion, expectedChunks);
|
||||
}
|
||||
|
||||
HWTEST_F(StagingBufferManagerTest, givenStagingBufferWhenGpuHangDuringChunkReadFromImageThenReturnImmediatelyWithFailure) {
|
||||
size_t expectedChunks = 4;
|
||||
const size_t globalOrigin[3] = {0, 0, 0};
|
||||
|
@ -541,7 +569,7 @@ HWTEST_F(StagingBufferManagerTest, givenStagingBufferWhenGpuHangDuringChunkReadF
|
|||
};
|
||||
auto ultCsr = reinterpret_cast<UltCommandStreamReceiver<FamilyType> *>(csr);
|
||||
ultCsr->waitForTaskCountReturnValue = WaitStatus::gpuHang;
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, chunkWrite, csr, true);
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, pixelElemSize, chunkWrite, csr, true);
|
||||
EXPECT_EQ(0, ret.chunkCopyStatus);
|
||||
EXPECT_EQ(WaitStatus::gpuHang, ret.waitStatus);
|
||||
EXPECT_EQ(2u, chunkCounter);
|
||||
|
@ -563,7 +591,7 @@ HWTEST_F(StagingBufferManagerTest, givenStagingBufferWhenGpuHangAfterChunkReadFr
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, chunkWrite, csr, true);
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, pixelElemSize, chunkWrite, csr, true);
|
||||
EXPECT_EQ(0, ret.chunkCopyStatus);
|
||||
EXPECT_EQ(WaitStatus::gpuHang, ret.waitStatus);
|
||||
EXPECT_EQ(4u, chunkCounter);
|
||||
|
@ -586,7 +614,7 @@ HWTEST_F(StagingBufferManagerTest, givenStagingBufferWhenGpuHangDuringRemainderC
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, chunkWrite, csr, true);
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, pixelElemSize, chunkWrite, csr, true);
|
||||
EXPECT_EQ(0, ret.chunkCopyStatus);
|
||||
EXPECT_EQ(WaitStatus::gpuHang, ret.waitStatus);
|
||||
EXPECT_EQ(remainderCounter - 1, chunkCounter);
|
||||
|
@ -605,7 +633,7 @@ TEST_F(StagingBufferManagerTest, givenStagingBufferWhenFailedChunkImageWriteThen
|
|||
++chunkCounter;
|
||||
return expectedErrorCode;
|
||||
};
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, chunkWrite, csr, false);
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, pixelElemSize, chunkWrite, csr, false);
|
||||
EXPECT_EQ(expectedErrorCode, ret.chunkCopyStatus);
|
||||
EXPECT_EQ(WaitStatus::ready, ret.waitStatus);
|
||||
EXPECT_EQ(1u, chunkCounter);
|
||||
|
@ -628,7 +656,7 @@ TEST_F(StagingBufferManagerTest, givenStagingBufferWhenFailedChunkImageWriteWith
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, chunkWrite, csr, false);
|
||||
auto ret = stagingBufferManager->performImageTransfer(ptr, globalOrigin, globalRegion, MemoryConstants::megaByte, pixelElemSize, chunkWrite, csr, false);
|
||||
EXPECT_EQ(expectedErrorCode, ret.chunkCopyStatus);
|
||||
EXPECT_EQ(WaitStatus::ready, ret.waitStatus);
|
||||
EXPECT_EQ(remainderCounter, chunkCounter);
|
||||
|
|
Loading…
Reference in New Issue