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:
Szymon Morek 2025-02-11 12:21:53 +00:00 committed by Compute-Runtime-Automation
parent e82ee0fd70
commit 8152241693
4 changed files with 109 additions and 55 deletions

View File

@ -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);
}

View File

@ -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 &currentStagingBuffers, CommandStreamReceiver *csr, Func &func, Args... args) {
StagingTransferStatus StagingBufferManager::performChunkTransfer(size_t chunkTransferId, bool isRead, const UserData &userData, StagingQueue &currentStagingBuffers, 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;
}

View File

@ -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 &currentStagingBuffers, CommandStreamReceiver *csr, Func &func, Args... args);
StagingTransferStatus performChunkTransfer(size_t chunkTransferId, bool isRead, const UserData &userData, StagingQueue &currentStagingBuffers, 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);

View File

@ -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);