Fix Buffer mapState after destroyed in Wire

WebGPU specification described that Buffer mapState must be
"unmapped" after destroyed because Destroy() must internally
call Unmap().

But in the current Wire implementation the mapState won't be
"unmapped". The root issue is that Destroy() doesn't update
mMapState in Wire.

This commit fixes the problem by updating mMapState in
Destroy() in Wire.

bug: dawn:1634
Change-Id: I7398510f83ebacfbc6bb33fcc070c2eab10b9c24
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/116820
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Takahiro <hogehoge@gachapin.jp>
This commit is contained in:
Takahiro 2023-01-12 02:07:48 +00:00 committed by Dawn LUCI CQ
parent dc9c306a14
commit 46e3e213b0
2 changed files with 100 additions and 5 deletions

View File

@ -1104,40 +1104,134 @@ TEST_F(BufferValidationTest, CreationParameterReflectionNoInternalUsage) {
// Test that GetMapState() shows expected buffer map state
TEST_F(BufferValidationTest, GetMapState) {
// MapRead
// MapRead + MapAsync + Unmap
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
buf.MapAsync(wgpu::MapMode::Read, 0, 4, nullptr, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MapRead + MapAsync + Unmap before the callback
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
EXPECT_CALL(*mockBufferMapAsyncCallback,
Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MapRead + MapAsync + Destroy
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MapWrite
// MapRead + MapAsync + Destroy before the callback
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
EXPECT_CALL(*mockBufferMapAsyncCallback,
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MapWrite + MapAsync + Unmap
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
buf.MapAsync(wgpu::MapMode::Write, 0, 4, nullptr, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MapWrite + MapAsync + Unmap before the callback
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
EXPECT_CALL(*mockBufferMapAsyncCallback,
Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MapWrite + MapAsync + Destroy
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MappedAtCreation
// MapWrite + MapAsync + Destroy before the callback
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
EXPECT_CALL(*mockBufferMapAsyncCallback,
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
.Times(1);
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
WaitForAllOperations(device);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MappedAtCreation + Unmap
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MappedAtCreation + Destroy
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}

View File

@ -370,6 +370,7 @@ void Buffer::Destroy() {
// Remove the current mapping and destroy Read/WriteHandles.
FreeMappedData();
mMapState = MapState::Unmapped;
InvokeAndClearCallback(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback);