Add Buffer.GetMapState()

Bug: dawn:1521
Change-Id: I68962a4d6b17867cd17cfcb3a17910a2007764fa
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/111924
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Takahiro <hogehoge@gachapin.jp>
This commit is contained in:
Takahiro 2022-12-19 19:06:51 +00:00 committed by Dawn LUCI CQ
parent 5abda5fa2c
commit 915e55a0d8
8 changed files with 146 additions and 1 deletions

View File

@ -445,6 +445,10 @@
"name": "get size",
"returns": "uint64_t"
},
{
"name": "get map state",
"returns": "buffer map state"
},
{
"name": "unmap"
},
@ -482,6 +486,14 @@
{"value": 5, "name": "unmapped before callback"}
]
},
"buffer map state": {
"category": "enum",
"values": [
{"value": 0, "name": "unmapped"},
{"value": 1, "name": "pending"},
{"value": 2, "name": "mapped"}
]
},
"buffer usage": {
"category": "bitmask",
"values": [

View File

@ -189,6 +189,7 @@
"BufferMapAsync",
"BufferGetConstMappedRange",
"BufferGetMappedRange",
"BufferGetMapState",
"BufferGetSize",
"BufferGetUsage",
"DeviceCreateBuffer",

View File

@ -239,6 +239,19 @@ wgpu::BufferUsage BufferBase::APIGetUsage() const {
return mUsage & ~kAllInternalBufferUsages;
}
wgpu::BufferMapState BufferBase::APIGetMapState() const {
switch (mState) {
case BufferState::Mapped:
case BufferState::MappedAtCreation:
return wgpu::BufferMapState::Mapped;
case BufferState::PendingMap:
return wgpu::BufferMapState::Pending;
case BufferState::Unmapped:
case BufferState::Destroyed:
return wgpu::BufferMapState::Unmapped;
}
}
MaybeError BufferBase::MapAtCreation() {
DAWN_TRY(MapAtCreationInternal());

View File

@ -86,6 +86,7 @@ class BufferBase : public ApiObjectBase {
void APIUnmap();
void APIDestroy();
wgpu::BufferUsage APIGetUsage() const;
wgpu::BufferMapState APIGetMapState() const;
uint64_t APIGetSize() const;
protected:

View File

@ -1101,3 +1101,44 @@ TEST_F(BufferValidationTest, CreationParameterReflectionNoInternalUsage) {
EXPECT_EQ(wgpu::BufferUsage::QueryResolve, buf.GetUsage());
EXPECT_EQ(16u, buf.GetSize());
}
// Test that GetMapState() shows expected buffer map state
TEST_F(BufferValidationTest, GetMapState) {
// MapRead
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
buf.MapAsync(wgpu::MapMode::Read, 0, 4, nullptr, 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());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MapWrite
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
buf.MapAsync(wgpu::MapMode::Write, 0, 4, nullptr, 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());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
// MappedAtCreation
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
}

View File

@ -746,7 +746,7 @@ TEST_F(WireBufferMappingTests, MapAfterDisconnect) {
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, this);
}
// Test that mappinga again while pending map immediately cause an error
// Test that mapping again while pending map immediately cause an error
TEST_F(WireBufferMappingTests, PendingMapImmediateError) {
SetupBuffer(WGPUMapMode_Read);
@ -756,6 +756,66 @@ TEST_F(WireBufferMappingTests, PendingMapImmediateError) {
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, this);
}
// Test that GetMapState() returns map state as expected
TEST_F(WireBufferMappingTests, GetMapState) {
SetupBuffer(WGPUMapMode_Read);
// Server-side success case
{
uint32_t bufferContent = 31337;
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
.WillOnce(InvokeWithoutArgs([&]() {
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
}));
EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
.WillOnce(Return(&bufferContent));
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Unmapped);
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
nullptr);
// map state should become pending immediately after map async call
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Pending);
FlushClient();
// map state should be pending until receiving a response from server
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Pending);
FlushServer();
// mapping succeeded
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Mapped);
}
wgpuBufferUnmap(buffer);
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
FlushClient();
// Server-side error case
{
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
.WillOnce(InvokeWithoutArgs([&]() {
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
}));
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Unmapped);
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
nullptr);
// map state should become pending immediately after map async call
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Pending);
FlushClient();
// map state should be pending until receiving a response from server
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Pending);
FlushServer();
// mapping failed
ASSERT_EQ(wgpuBufferGetMapState(buffer), WGPUBufferMapState_Unmapped);
}
}
// Hack to pass in test context into user callback
struct TestData {
WireBufferMappingTests* pTest;

View File

@ -386,6 +386,21 @@ uint64_t Buffer::GetSize() const {
return mSize;
}
WGPUBufferMapState Buffer::GetMapState() const {
switch (mMapState) {
case MapState::MappedForRead:
case MapState::MappedForWrite:
case MapState::MappedAtCreation:
return WGPUBufferMapState_Mapped;
case MapState::Unmapped:
if (mPendingMap) {
return WGPUBufferMapState_Pending;
} else {
return WGPUBufferMapState_Unmapped;
}
}
}
bool Buffer::IsMappedForReading() const {
return mMapState == MapState::MappedForRead;
}

View File

@ -52,6 +52,8 @@ class Buffer final : public ObjectBase {
WGPUBufferUsage GetUsage() const;
uint64_t GetSize() const;
WGPUBufferMapState GetMapState() const;
private:
void CancelCallbacksForDisconnect() override;
void InvokeAndClearCallback(WGPUBufferMapAsyncStatus status);