Skip to content

Commit 41fb614

Browse files
GPUUploadManager: add tests for Page::Writer::ScheduleBufferUpdates
1 parent fbbaf61 commit 41fb614

File tree

1 file changed

+186
-21
lines changed

1 file changed

+186
-21
lines changed

Tests/DiligentCoreAPITest/src/GPUUploadManagerTest.cpp

Lines changed: 186 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,157 @@ void VerifyBufferContents(IBuffer* pBuffer, const std::vector<Uint8>& ExpectedDa
105105
pContext->UnmapBuffer(pReadbackBuffer, MAP_READ);
106106
}
107107

108+
109+
void TestWriterScheduleBufferUpdates(bool UseWriteCallback, bool UseCopyCallback)
110+
{
111+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
112+
IRenderDevice* pDevice = pEnv->GetDevice();
113+
IDeviceContext* pContext = pEnv->GetDeviceContext();
114+
115+
GPUTestingEnvironment::ScopedReset AutoReset;
116+
117+
std::vector<Uint8> BufferData(8192);
118+
for (size_t i = 0; i < BufferData.size(); ++i)
119+
{
120+
BufferData[i] = static_cast<Uint8>(i % 256);
121+
}
122+
123+
static constexpr Uint32 kNumUpdates = 10;
124+
constexpr std::array<Uint32, kNumUpdates> UpdateSizes = {256, 512, 256, 1024, 2048, 1024, 2048, 512, 256, 256};
125+
126+
BufferDesc Desc;
127+
Desc.Name = "GPUUploadManagerTest buffer";
128+
Desc.Size = BufferData.size();
129+
Desc.Usage = USAGE_DEFAULT;
130+
Desc.BindFlags = BIND_VERTEX_BUFFER;
131+
132+
RefCntAutoPtr<IBuffer> pBuffer;
133+
pDevice->CreateBuffer(Desc, nullptr, &pBuffer);
134+
ASSERT_TRUE(pBuffer);
135+
136+
Uint32 CurrOffset = 0;
137+
138+
GPUUploadManagerImpl::Page Page{nullptr, pDevice, static_cast<Uint32>(BufferData.size())};
139+
Page.Reset(pContext);
140+
Page.Unseal();
141+
142+
GPUUploadManagerImpl::Page::Writer Writer = Page.TryBeginWriting();
143+
EXPECT_TRUE(Writer) << "Should be able to begin writing to a new page";
144+
145+
Uint32 NumWriteDataCallbackCalled = 0;
146+
147+
auto WriteDataCallback = MakeCallback([&](void* pDstData, Uint32 NumBytes) {
148+
std::memcpy(pDstData, &BufferData[CurrOffset], NumBytes);
149+
++NumWriteDataCallbackCalled;
150+
});
151+
152+
Uint32 NumCopyBufferCallbackCalled = 0;
153+
Uint32 CopyBufferCallbackDstOffset = 0;
154+
155+
auto CopyBufferCallback = MakeCallback([&](IDeviceContext* pContext,
156+
IBuffer* pSrcBuffer,
157+
Uint32 SrcOffset,
158+
Uint32 NumBytes) {
159+
EXPECT_EQ(NumBytes, UpdateSizes[NumCopyBufferCallbackCalled]);
160+
pContext->CopyBuffer(pSrcBuffer, SrcOffset, RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
161+
pBuffer, CopyBufferCallbackDstOffset, NumBytes, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
162+
CopyBufferCallbackDstOffset += NumBytes;
163+
++NumCopyBufferCallbackCalled;
164+
});
165+
166+
Uint32 NumUploadEnqueuedCallbackCalled = 0;
167+
Uint32 UploadEnqueuedCallbackDstOffset = 0;
168+
169+
auto UploadEnqueuedCallback = MakeCallback(
170+
[&](IBuffer* pDstBuffer,
171+
Uint32 DstOffset,
172+
Uint32 NumBytes) {
173+
EXPECT_EQ(NumBytes, UpdateSizes[NumUploadEnqueuedCallbackCalled]);
174+
EXPECT_EQ(DstOffset, UploadEnqueuedCallbackDstOffset);
175+
UploadEnqueuedCallbackDstOffset += NumBytes;
176+
++NumUploadEnqueuedCallbackCalled;
177+
});
178+
179+
for (Uint32 NumBytes : UpdateSizes)
180+
{
181+
ScheduleBufferUpdateInfo UpdateInfo;
182+
UpdateInfo.NumBytes = NumBytes;
183+
184+
if (UseCopyCallback)
185+
{
186+
UpdateInfo.CopyBuffer = CopyBufferCallback;
187+
UpdateInfo.pCopyBufferData = CopyBufferCallback;
188+
}
189+
else
190+
{
191+
UpdateInfo.pDstBuffer = pBuffer;
192+
UpdateInfo.DstOffset = CurrOffset;
193+
}
194+
195+
if (UseWriteCallback)
196+
{
197+
UpdateInfo.WriteDataCallback = WriteDataCallback;
198+
UpdateInfo.pWriteDataCallbackUserData = WriteDataCallback;
199+
}
200+
else
201+
{
202+
UpdateInfo.pSrcData = &BufferData[CurrOffset];
203+
}
204+
205+
UpdateInfo.UploadEnqueued = UploadEnqueuedCallback;
206+
UpdateInfo.pUploadEnqueuedData = UploadEnqueuedCallback;
207+
208+
EXPECT_TRUE(Writer.ScheduleBufferUpdate(UpdateInfo));
209+
210+
CurrOffset += NumBytes;
211+
}
212+
VERIFY_EXPR(CurrOffset == BufferData.size());
213+
214+
{
215+
ScheduleBufferUpdateInfo UpdateInfo;
216+
UpdateInfo.pDstBuffer = pBuffer;
217+
UpdateInfo.NumBytes = 16;
218+
UpdateInfo.DstOffset = 0;
219+
UpdateInfo.pSrcData = &BufferData[0];
220+
EXPECT_FALSE(Writer.ScheduleBufferUpdate(UpdateInfo)) << "Should not be able to schedule updates when the page is full";
221+
}
222+
223+
EXPECT_EQ(Page.GetNumPendingOps(), UpdateSizes.size());
224+
EXPECT_TRUE(Writer.EndWriting() == GPUUploadManagerImpl::Page::WritingStatus::NotSealed) << "Page should not be sealed";
225+
226+
EXPECT_EQ(Page.TrySeal(), GPUUploadManagerImpl::Page::SealStatus::Ready) << "Page with no active writers should be ready immediately";
227+
EXPECT_EQ(Page.GetNumPendingOps(), UpdateSizes.size());
228+
Page.ExecutePendingOps(pContext, 1);
229+
EXPECT_EQ(Page.GetNumPendingOps(), size_t{0});
230+
EXPECT_EQ(NumUploadEnqueuedCallbackCalled, UseCopyCallback ? 0u : kNumUpdates);
231+
Page.ReleaseStagingBuffer(pContext);
232+
233+
EXPECT_EQ(UseWriteCallback ? kNumUpdates : 0u, NumWriteDataCallbackCalled);
234+
EXPECT_EQ(UseCopyCallback ? kNumUpdates : 0u, NumCopyBufferCallbackCalled);
235+
236+
VerifyBufferContents(pBuffer, BufferData);
237+
}
238+
239+
TEST(GPUUploadManagerTest, Writer_ScheduleBufferUpdates)
240+
{
241+
TestWriterScheduleBufferUpdates(/*UseWriteCallback = */ false, /*UseCopyCallback = */ false);
242+
}
243+
244+
TEST(GPUUploadManagerTest, Writer_ScheduleBufferUpdatesWithWriteBufferCallback)
245+
{
246+
TestWriterScheduleBufferUpdates(/*UseWriteCallback = */ true, /*UseCopyCallback = */ false);
247+
}
248+
249+
TEST(GPUUploadManagerTest, Writer_ScheduleBufferUpdatesWithCopyBufferCallback)
250+
{
251+
TestWriterScheduleBufferUpdates(/*UseWriteCallback = */ false, /*UseCopyCallback = */ true);
252+
}
253+
254+
TEST(GPUUploadManagerTest, Writer_ScheduleBufferUpdatesWithWriteAndCopyCallbacks)
255+
{
256+
TestWriterScheduleBufferUpdates(/*UseWriteCallback = */ true, /*UseCopyCallback = */ true);
257+
}
258+
108259
TEST(GPUUploadManagerTest, ScheduleBufferUpdates)
109260
{
110261
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
@@ -184,22 +335,22 @@ TEST(GPUUploadManagerTest, ScheduleBufferUpdatesWithCopyBufferCallback)
184335

185336
Uint32 CurrOffset = 0;
186337

187-
auto GetDstBufferInfo = MakeCallback([&](IDeviceContext* pContext,
188-
IBuffer* pSrcBuffer,
189-
Uint32 SrcOffset,
190-
Uint32 NumBytes) {
338+
auto CopyBufferCallback = MakeCallback([&](IDeviceContext* pContext,
339+
IBuffer* pSrcBuffer,
340+
Uint32 SrcOffset,
341+
Uint32 NumBytes) {
191342
pContext->CopyBuffer(pSrcBuffer, SrcOffset, RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
192343
pBuffer, CurrOffset, NumBytes, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
193344
CurrOffset += NumBytes;
194345
});
195346

196-
pUploadManager->ScheduleBufferUpdate({pContext, 256, &BufferData[0], GetDstBufferInfo, GetDstBufferInfo});
197-
pUploadManager->ScheduleBufferUpdate({pContext, 256, &BufferData[256], GetDstBufferInfo, GetDstBufferInfo});
198-
pUploadManager->ScheduleBufferUpdate({pContext, 1024, &BufferData[512], GetDstBufferInfo, GetDstBufferInfo});
199-
pUploadManager->ScheduleBufferUpdate({pContext, 512, &BufferData[1536], GetDstBufferInfo, GetDstBufferInfo});
200-
pUploadManager->ScheduleBufferUpdate({pContext, 2048, &BufferData[2048], GetDstBufferInfo, GetDstBufferInfo});
201-
pUploadManager->ScheduleBufferUpdate({pContext, 4096, &BufferData[4096], GetDstBufferInfo, GetDstBufferInfo});
202-
pUploadManager->ScheduleBufferUpdate({pContext, 8192, &BufferData[8192], GetDstBufferInfo, GetDstBufferInfo});
347+
pUploadManager->ScheduleBufferUpdate({pContext, 256, &BufferData[0], CopyBufferCallback, CopyBufferCallback});
348+
pUploadManager->ScheduleBufferUpdate({pContext, 256, &BufferData[256], CopyBufferCallback, CopyBufferCallback});
349+
pUploadManager->ScheduleBufferUpdate({pContext, 1024, &BufferData[512], CopyBufferCallback, CopyBufferCallback});
350+
pUploadManager->ScheduleBufferUpdate({pContext, 512, &BufferData[1536], CopyBufferCallback, CopyBufferCallback});
351+
pUploadManager->ScheduleBufferUpdate({pContext, 2048, &BufferData[2048], CopyBufferCallback, CopyBufferCallback});
352+
pUploadManager->ScheduleBufferUpdate({pContext, 4096, &BufferData[4096], CopyBufferCallback, CopyBufferCallback});
353+
pUploadManager->ScheduleBufferUpdate({pContext, 8192, &BufferData[8192], CopyBufferCallback, CopyBufferCallback});
203354

204355
pUploadManager->RenderThreadUpdate(pContext);
205356
pUploadManager->RenderThreadUpdate(pContext);
@@ -802,8 +953,8 @@ void TestWriterScheduleTextureUpdates(Uint32 Flags = TEST_TEXTURE_UPDATES_FLAGS_
802953
Page->Reset(pContext);
803954
Page->Unseal();
804955

805-
bool WriteDataCallbackCalled = false;
806-
bool CopyTextureCallbackCalled = false;
956+
Uint32 NumWriteDataCallbackCalled = 0;
957+
Uint32 NumCopyTextureCallbackCalled = 0;
807958

808959
auto WriteDataCallback = MakeCallback([&](void* pDstData, Uint32 Stride, Uint32 DepthStride, const Box& DstBox) {
809960
for (Uint32 row = 0; row < DstBox.Height(); ++row)
@@ -812,15 +963,15 @@ void TestWriterScheduleTextureUpdates(Uint32 Flags = TEST_TEXTURE_UPDATES_FLAGS_
812963
void* pDstRow = static_cast<Uint8*>(pDstData) + row * Stride;
813964
std::memcpy(pDstRow, pSrcRow, DstBox.Width() * ElementSize);
814965
}
815-
WriteDataCallbackCalled = true;
966+
++NumWriteDataCallbackCalled;
816967
});
817968

818969
struct CopyTextureCallbackData
819970
{
820971
ITexture* const pDstTexture;
821-
bool& CopyTextureCallbackCalled;
972+
Uint32& NumCopyTextureCallbackCalled;
822973
};
823-
CopyTextureCallbackData CopyCallbackData{pTexture, CopyTextureCallbackCalled};
974+
CopyTextureCallbackData CopyCallbackData{pTexture, NumCopyTextureCallbackCalled};
824975

825976
auto CopyTextureCallback = [](IDeviceContext* pContext,
826977
Uint32 DstMipLevel,
@@ -832,7 +983,7 @@ void TestWriterScheduleTextureUpdates(Uint32 Flags = TEST_TEXTURE_UPDATES_FLAGS_
832983
pContext->UpdateTexture(pCallbackData->pDstTexture, DstMipLevel, DstSlice, DstBox, SrcData,
833984
RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
834985
RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
835-
pCallbackData->CopyTextureCallbackCalled = true;
986+
++pCallbackData->NumCopyTextureCallbackCalled;
836987
};
837988

838989
auto CopyD3D11TextureCallback = [](IDeviceContext* pContext,
@@ -865,9 +1016,18 @@ void TestWriterScheduleTextureUpdates(Uint32 Flags = TEST_TEXTURE_UPDATES_FLAGS_
8651016
CopyAttribs.DstTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
8661017

8671018
pContext->CopyTexture(CopyAttribs);
868-
pCallbackData->CopyTextureCallbackCalled = true;
1019+
++pCallbackData->NumCopyTextureCallbackCalled;
8691020
};
8701021

1022+
Uint32 NumUploadEnqueuedCallbackCalled = 0;
1023+
1024+
auto UploadEnqueuedCallback = MakeCallback([&](ITexture* pDstTexture,
1025+
Uint32 DstMipLevel,
1026+
Uint32 DstSlice,
1027+
const Box& DstBox) {
1028+
++NumUploadEnqueuedCallbackCalled;
1029+
});
1030+
8711031
{
8721032
GPUUploadManagerImpl::Page::Writer Writer = Page->TryBeginWriting();
8731033
EXPECT_TRUE(Writer) << "Should be able to begin writing to a new page";
@@ -899,6 +1059,10 @@ void TestWriterScheduleTextureUpdates(Uint32 Flags = TEST_TEXTURE_UPDATES_FLAGS_
8991059
UpdateInfo.pSrcData = &Mip0Data[(UpdateInfo.DstBox.MinX + UpdateInfo.DstBox.MinY * TexDesc.Width) * ElementSize];
9001060
UpdateInfo.Stride = TexDesc.Width * ElementSize;
9011061
}
1062+
1063+
UpdateInfo.UploadEnqueued = UploadEnqueuedCallback;
1064+
UpdateInfo.pUploadEnqueuedData = UploadEnqueuedCallback;
1065+
9021066
return Writer.ScheduleTextureUpdate(UpdateInfo, GetBufferToTextureCopyInfo(TexDesc.Format, UpdateInfo.DstBox, 1024), 1024);
9031067
};
9041068

@@ -920,10 +1084,11 @@ void TestWriterScheduleTextureUpdates(Uint32 Flags = TEST_TEXTURE_UPDATES_FLAGS_
9201084
EXPECT_EQ(Page->GetNumPendingOps(), size_t{4});
9211085
Page->ExecutePendingOps(pContext, 1);
9221086
EXPECT_EQ(Page->GetNumPendingOps(), size_t{0});
1087+
EXPECT_EQ(NumUploadEnqueuedCallbackCalled, (Flags & TEST_TEXTURE_UPDATES_FLAGS_USE_COPY_CALLBACK) ? 0u : 4u);
9231088
Page->ReleaseStagingBuffer(pContext);
9241089

925-
EXPECT_EQ((Flags & TEST_TEXTURE_UPDATES_FLAGS_USE_WRITE_DATA_CALLBACK) != 0, WriteDataCallbackCalled);
926-
EXPECT_EQ((Flags & TEST_TEXTURE_UPDATES_FLAGS_USE_COPY_CALLBACK) != 0, CopyTextureCallbackCalled);
1090+
EXPECT_EQ((Flags & TEST_TEXTURE_UPDATES_FLAGS_USE_WRITE_DATA_CALLBACK) ? 4u : 0u, NumWriteDataCallbackCalled);
1091+
EXPECT_EQ((Flags & TEST_TEXTURE_UPDATES_FLAGS_USE_COPY_CALLBACK) ? 4u : 0u, NumCopyTextureCallbackCalled);
9271092

9281093
VerifyTextureContents(pTexture, SubresData);
9291094
}
@@ -943,7 +1108,7 @@ TEST(GPUUploadManagerTest, Writer_ScheduleTextureUpdates_WithCopyCallback)
9431108
TestWriterScheduleTextureUpdates(TEST_TEXTURE_UPDATES_FLAGS_USE_COPY_CALLBACK);
9441109
}
9451110

946-
TEST(GPUUploadManagerTest, Writer_ScheduleTextureUpdates_WithWriteAndCopyCallback)
1111+
TEST(GPUUploadManagerTest, Writer_ScheduleTextureUpdates_WithWriteAndCopyCallbacks)
9471112
{
9481113
TestWriterScheduleTextureUpdates(TEST_TEXTURE_UPDATES_FLAGS_USE_WRITE_DATA_CALLBACK | TEST_TEXTURE_UPDATES_FLAGS_USE_COPY_CALLBACK);
9491114
}

0 commit comments

Comments
 (0)