Add Buffer::Get[|Const]MappedRange
This CL adds GetMappedRange reusing the existing GetMappedPointerImpl call in dawn_native. In dawn_wire tracking is added to keep a Buffer::mMappedData around. Tests are added to test the result of Get[|Const]MappedRange in all buffer states. Bug: dawn:445 Change-Id: I3737dc4d36f31d392839952da0b5c0d10c7c8a88 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23861 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
2008d15326
commit
1325ab1251
14
dawn.json
14
dawn.json
|
@ -197,6 +197,14 @@
|
||||||
{"name": "userdata", "type": "void", "annotation": "*"}
|
{"name": "userdata", "type": "void", "annotation": "*"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "get mapped range",
|
||||||
|
"returns": "void *"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "get const mapped range",
|
||||||
|
"returns": "void const *"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "unmap"
|
"name": "unmap"
|
||||||
},
|
},
|
||||||
|
@ -1690,6 +1698,12 @@
|
||||||
"void": {
|
"void": {
|
||||||
"category": "native"
|
"category": "native"
|
||||||
},
|
},
|
||||||
|
"void *": {
|
||||||
|
"category": "native"
|
||||||
|
},
|
||||||
|
"void const *": {
|
||||||
|
"category": "native"
|
||||||
|
},
|
||||||
"uint32_t": {
|
"uint32_t": {
|
||||||
"category": "native"
|
"category": "native"
|
||||||
},
|
},
|
||||||
|
|
|
@ -97,6 +97,8 @@
|
||||||
"BufferMapReadAsync",
|
"BufferMapReadAsync",
|
||||||
"BufferMapWriteAsync",
|
"BufferMapWriteAsync",
|
||||||
"BufferSetSubData",
|
"BufferSetSubData",
|
||||||
|
"BufferGetConstMappedRange",
|
||||||
|
"BufferGetMappedRange",
|
||||||
"DevicePopErrorScope",
|
"DevicePopErrorScope",
|
||||||
"DeviceSetDeviceLostCallback",
|
"DeviceSetDeviceLostCallback",
|
||||||
"DeviceSetUncapturedErrorCallback",
|
"DeviceSetUncapturedErrorCallback",
|
||||||
|
|
|
@ -305,6 +305,26 @@ namespace dawn_native {
|
||||||
tracker->Track(this, mMapSerial, true);
|
tracker->Track(this, mMapSerial, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* BufferBase::GetMappedRange() {
|
||||||
|
if (GetDevice()->ConsumedError(ValidateGetMappedRange(true))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (mStagingBuffer != nullptr) {
|
||||||
|
return mStagingBuffer->GetMappedPointer();
|
||||||
|
}
|
||||||
|
return GetMappedPointerImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* BufferBase::GetConstMappedRange() {
|
||||||
|
if (GetDevice()->ConsumedError(ValidateGetMappedRange(false))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (mStagingBuffer != nullptr) {
|
||||||
|
return mStagingBuffer->GetMappedPointer();
|
||||||
|
}
|
||||||
|
return GetMappedPointerImpl();
|
||||||
|
}
|
||||||
|
|
||||||
void BufferBase::Destroy() {
|
void BufferBase::Destroy() {
|
||||||
if (IsError()) {
|
if (IsError()) {
|
||||||
// It is an error to call Destroy() on an ErrorBuffer, but we still need to reclaim the
|
// It is an error to call Destroy() on an ErrorBuffer, but we still need to reclaim the
|
||||||
|
@ -406,6 +426,29 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeError BufferBase::ValidateGetMappedRange(bool writable) const {
|
||||||
|
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||||
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
|
||||||
|
switch (mState) {
|
||||||
|
// Writeable Buffer::GetMappedRange is always allowed when mapped at creation.
|
||||||
|
case BufferState::MappedAtCreation:
|
||||||
|
return {};
|
||||||
|
|
||||||
|
case BufferState::Mapped:
|
||||||
|
if (writable && !(mUsage & wgpu::BufferUsage::MapWrite)) {
|
||||||
|
return DAWN_VALIDATION_ERROR("GetMappedRange requires the MapWrite usage");
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
|
||||||
|
case BufferState::Unmapped:
|
||||||
|
case BufferState::Destroyed:
|
||||||
|
return DAWN_VALIDATION_ERROR("Buffer is not mapped");
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MaybeError BufferBase::ValidateUnmap() const {
|
MaybeError BufferBase::ValidateUnmap() const {
|
||||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
|
|
@ -61,6 +61,8 @@ namespace dawn_native {
|
||||||
void SetSubData(uint32_t start, uint32_t count, const void* data);
|
void SetSubData(uint32_t start, uint32_t count, const void* data);
|
||||||
void MapReadAsync(WGPUBufferMapReadCallback callback, void* userdata);
|
void MapReadAsync(WGPUBufferMapReadCallback callback, void* userdata);
|
||||||
void MapWriteAsync(WGPUBufferMapWriteCallback callback, void* userdata);
|
void MapWriteAsync(WGPUBufferMapWriteCallback callback, void* userdata);
|
||||||
|
void* GetMappedRange();
|
||||||
|
const void* GetConstMappedRange();
|
||||||
void Unmap();
|
void Unmap();
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
@ -94,6 +96,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError ValidateMap(wgpu::BufferUsage requiredUsage,
|
MaybeError ValidateMap(wgpu::BufferUsage requiredUsage,
|
||||||
WGPUBufferMapAsyncStatus* status) const;
|
WGPUBufferMapAsyncStatus* status) const;
|
||||||
|
MaybeError ValidateGetMappedRange(bool writable) const;
|
||||||
MaybeError ValidateUnmap() const;
|
MaybeError ValidateUnmap() const;
|
||||||
MaybeError ValidateDestroy() const;
|
MaybeError ValidateDestroy() const;
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Buffer::GetMappedPointerImpl() {
|
void* Buffer::GetMappedPointerImpl() {
|
||||||
return reinterpret_cast<uint8_t*>([mMtlBuffer contents]);
|
return [mMtlBuffer contents];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::UnmapImpl() {
|
void Buffer::UnmapImpl() {
|
||||||
|
|
|
@ -40,6 +40,16 @@ namespace dawn_wire { namespace client {
|
||||||
buffer->SetSubData(start, count, data);
|
buffer->SetSubData(start, count, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* ClientHandwrittenBufferGetMappedRange(WGPUBuffer cBuffer) {
|
||||||
|
Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer);
|
||||||
|
return buffer->GetMappedRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* ClientHandwrittenBufferGetConstMappedRange(WGPUBuffer cBuffer) {
|
||||||
|
Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer);
|
||||||
|
return buffer->GetConstMappedRange();
|
||||||
|
}
|
||||||
|
|
||||||
void ClientHandwrittenBufferUnmap(WGPUBuffer cBuffer) {
|
void ClientHandwrittenBufferUnmap(WGPUBuffer cBuffer) {
|
||||||
Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer);
|
Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer);
|
||||||
buffer->Unmap();
|
buffer->Unmap();
|
||||||
|
|
|
@ -122,6 +122,7 @@ namespace dawn_wire { namespace client {
|
||||||
buffer->mSize = descriptor->size;
|
buffer->mSize = descriptor->size;
|
||||||
// Successfully created staging memory. The buffer now owns the WriteHandle.
|
// Successfully created staging memory. The buffer now owns the WriteHandle.
|
||||||
buffer->mWriteHandle = std::move(writeHandle);
|
buffer->mWriteHandle = std::move(writeHandle);
|
||||||
|
buffer->mMappedData = result.data;
|
||||||
|
|
||||||
result.buffer = reinterpret_cast<WGPUBuffer>(buffer);
|
result.buffer = reinterpret_cast<WGPUBuffer>(buffer);
|
||||||
|
|
||||||
|
@ -252,8 +253,8 @@ namespace dawn_wire { namespace client {
|
||||||
// second time. If, for example, buffer.Unmap() is called inside the callback.
|
// second time. If, for example, buffer.Unmap() is called inside the callback.
|
||||||
mRequests.erase(requestIt);
|
mRequests.erase(requestIt);
|
||||||
|
|
||||||
const void* mappedData = nullptr;
|
|
||||||
size_t mappedDataLength = 0;
|
size_t mappedDataLength = 0;
|
||||||
|
const void* mappedData = nullptr;
|
||||||
|
|
||||||
auto GetMappedData = [&]() -> bool {
|
auto GetMappedData = [&]() -> bool {
|
||||||
// It is an error for the server to call the read callback when we asked for a map write
|
// It is an error for the server to call the read callback when we asked for a map write
|
||||||
|
@ -298,7 +299,8 @@ namespace dawn_wire { namespace client {
|
||||||
request.readCallback(WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0, request.userdata);
|
request.readCallback(WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0, request.userdata);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
request.readCallback(static_cast<WGPUBufferMapAsyncStatus>(status), mappedData,
|
mMappedData = const_cast<void*>(mappedData);
|
||||||
|
request.readCallback(static_cast<WGPUBufferMapAsyncStatus>(status), mMappedData,
|
||||||
static_cast<uint64_t>(mappedDataLength), request.userdata);
|
static_cast<uint64_t>(mappedDataLength), request.userdata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -316,8 +318,8 @@ namespace dawn_wire { namespace client {
|
||||||
// second time. If, for example, buffer.Unmap() is called inside the callback.
|
// second time. If, for example, buffer.Unmap() is called inside the callback.
|
||||||
mRequests.erase(requestIt);
|
mRequests.erase(requestIt);
|
||||||
|
|
||||||
void* mappedData = nullptr;
|
|
||||||
size_t mappedDataLength = 0;
|
size_t mappedDataLength = 0;
|
||||||
|
void* mappedData = nullptr;
|
||||||
|
|
||||||
auto GetMappedData = [&]() -> bool {
|
auto GetMappedData = [&]() -> bool {
|
||||||
// It is an error for the server to call the write callback when we asked for a map read
|
// It is an error for the server to call the write callback when we asked for a map read
|
||||||
|
@ -355,12 +357,31 @@ namespace dawn_wire { namespace client {
|
||||||
request.userdata);
|
request.userdata);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
mMappedData = mappedData;
|
||||||
request.writeCallback(static_cast<WGPUBufferMapAsyncStatus>(status), mappedData,
|
request.writeCallback(static_cast<WGPUBufferMapAsyncStatus>(status), mappedData,
|
||||||
static_cast<uint64_t>(mappedDataLength), request.userdata);
|
static_cast<uint64_t>(mappedDataLength), request.userdata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* Buffer::GetMappedRange() {
|
||||||
|
if (!IsMappedForWriting()) {
|
||||||
|
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(device), WGPUErrorType_Validation,
|
||||||
|
"Buffer needs to be mapped for writing");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return mMappedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* Buffer::GetConstMappedRange() {
|
||||||
|
if (!IsMappedForWriting() && !IsMappedForReading()) {
|
||||||
|
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(device), WGPUErrorType_Validation,
|
||||||
|
"Buffer needs to be mapped");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return mMappedData;
|
||||||
|
}
|
||||||
|
|
||||||
void Buffer::Unmap() {
|
void Buffer::Unmap() {
|
||||||
// Invalidate the local pointer, and cancel all other in-flight requests that would
|
// Invalidate the local pointer, and cancel all other in-flight requests that would
|
||||||
// turn into errors anyway (you can't double map). This prevents race when the following
|
// turn into errors anyway (you can't double map). This prevents race when the following
|
||||||
|
@ -394,6 +415,7 @@ namespace dawn_wire { namespace client {
|
||||||
} else if (mReadHandle) {
|
} else if (mReadHandle) {
|
||||||
mReadHandle = nullptr;
|
mReadHandle = nullptr;
|
||||||
}
|
}
|
||||||
|
mMappedData = nullptr;
|
||||||
ClearMapRequests(WGPUBufferMapAsyncStatus_Unknown);
|
ClearMapRequests(WGPUBufferMapAsyncStatus_Unknown);
|
||||||
|
|
||||||
BufferUnmapCmd cmd;
|
BufferUnmapCmd cmd;
|
||||||
|
@ -405,6 +427,7 @@ namespace dawn_wire { namespace client {
|
||||||
// Cancel or remove all mappings
|
// Cancel or remove all mappings
|
||||||
mWriteHandle = nullptr;
|
mWriteHandle = nullptr;
|
||||||
mReadHandle = nullptr;
|
mReadHandle = nullptr;
|
||||||
|
mMappedData = nullptr;
|
||||||
ClearMapRequests(WGPUBufferMapAsyncStatus_Unknown);
|
ClearMapRequests(WGPUBufferMapAsyncStatus_Unknown);
|
||||||
|
|
||||||
BufferDestroyCmd cmd;
|
BufferDestroyCmd cmd;
|
||||||
|
@ -422,4 +445,12 @@ namespace dawn_wire { namespace client {
|
||||||
device->GetClient()->SerializeCommand(cmd);
|
device->GetClient()->SerializeCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Buffer::IsMappedForReading() const {
|
||||||
|
return mReadHandle != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::IsMappedForWriting() const {
|
||||||
|
return mWriteHandle != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace dawn_wire::client
|
}} // namespace dawn_wire::client
|
||||||
|
|
|
@ -42,12 +42,17 @@ namespace dawn_wire { namespace client {
|
||||||
uint64_t initialDataInfoLength,
|
uint64_t initialDataInfoLength,
|
||||||
const uint8_t* initialDataInfo);
|
const uint8_t* initialDataInfo);
|
||||||
bool OnMapWriteAsyncCallback(uint32_t requestSerial, uint32_t status);
|
bool OnMapWriteAsyncCallback(uint32_t requestSerial, uint32_t status);
|
||||||
|
void* GetMappedRange();
|
||||||
|
const void* GetConstMappedRange();
|
||||||
void Unmap();
|
void Unmap();
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
void SetSubData(uint64_t start, uint64_t count, const void* data);
|
void SetSubData(uint64_t start, uint64_t count, const void* data);
|
||||||
|
|
||||||
|
bool IsMappedForReading() const;
|
||||||
|
bool IsMappedForWriting() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// We want to defer all the validation to the server, which means we could have multiple
|
// We want to defer all the validation to the server, which means we could have multiple
|
||||||
// map request in flight at a single time and need to track them separately.
|
// map request in flight at a single time and need to track them separately.
|
||||||
|
@ -70,6 +75,7 @@ namespace dawn_wire { namespace client {
|
||||||
// TODO(enga): Use a tagged pointer to save space.
|
// TODO(enga): Use a tagged pointer to save space.
|
||||||
std::unique_ptr<MemoryTransferService::ReadHandle> mReadHandle = nullptr;
|
std::unique_ptr<MemoryTransferService::ReadHandle> mReadHandle = nullptr;
|
||||||
std::unique_ptr<MemoryTransferService::WriteHandle> mWriteHandle = nullptr;
|
std::unique_ptr<MemoryTransferService::WriteHandle> mWriteHandle = nullptr;
|
||||||
|
void* mMappedData = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_wire::client
|
}} // namespace dawn_wire::client
|
||||||
|
|
|
@ -119,6 +119,18 @@ TEST_P(BufferMapReadTests, ZeroSized) {
|
||||||
UnmapBuffer(buffer);
|
UnmapBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test the result of GetMappedRange when mapped for reading.
|
||||||
|
TEST_P(BufferMapReadTests, GetMappedRange) {
|
||||||
|
wgpu::BufferDescriptor descriptor;
|
||||||
|
descriptor.size = 4;
|
||||||
|
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
|
||||||
|
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||||
|
|
||||||
|
const void* mappedData = MapReadAsyncAndWait(buffer);
|
||||||
|
ASSERT_EQ(mappedData, buffer.GetConstMappedRange());
|
||||||
|
UnmapBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(BufferMapReadTests, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
DAWN_INSTANTIATE_TEST(BufferMapReadTests, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
||||||
|
|
||||||
class BufferMapWriteTests : public DawnTest {
|
class BufferMapWriteTests : public DawnTest {
|
||||||
|
@ -253,6 +265,19 @@ TEST_P(BufferMapWriteTests, ManyWrites) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test the result of GetMappedRange when mapped for writing.
|
||||||
|
TEST_P(BufferMapWriteTests, GetMappedRange) {
|
||||||
|
wgpu::BufferDescriptor descriptor;
|
||||||
|
descriptor.size = 4;
|
||||||
|
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
|
||||||
|
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||||
|
|
||||||
|
void* mappedData = MapWriteAsyncAndWait(buffer);
|
||||||
|
ASSERT_EQ(mappedData, buffer.GetMappedRange());
|
||||||
|
ASSERT_EQ(mappedData, buffer.GetConstMappedRange());
|
||||||
|
UnmapBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(BufferMapWriteTests, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
DAWN_INSTANTIATE_TEST(BufferMapWriteTests, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
|
||||||
|
|
||||||
// TODO(enga): These tests should use the testing toggle to initialize resources to 1.
|
// TODO(enga): These tests should use the testing toggle to initialize resources to 1.
|
||||||
|
@ -505,6 +530,19 @@ TEST_P(CreateBufferMappedTests, ZeroSizedErrorBuffer) {
|
||||||
ASSERT_NE(nullptr, result.data);
|
ASSERT_NE(nullptr, result.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test the result of GetMappedRange when mapped at creation.
|
||||||
|
TEST_P(CreateBufferMappedTests, GetMappedRange) {
|
||||||
|
wgpu::BufferDescriptor descriptor;
|
||||||
|
descriptor.size = 4;
|
||||||
|
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||||
|
wgpu::CreateBufferMappedResult result;
|
||||||
|
result = device.CreateBufferMapped(&descriptor);
|
||||||
|
|
||||||
|
ASSERT_EQ(result.data, result.buffer.GetMappedRange());
|
||||||
|
ASSERT_EQ(result.data, result.buffer.GetConstMappedRange());
|
||||||
|
result.buffer.Unmap();
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
|
DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
|
||||||
D3D12Backend(),
|
D3D12Backend(),
|
||||||
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
|
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
|
||||||
|
|
|
@ -662,3 +662,166 @@ TEST_F(BufferValidationTest, UnmapUnmappedBuffer) {
|
||||||
buf.Unmap();
|
buf.Unmap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that it is invalid to call GetMappedRange on an unmapped buffer.
|
||||||
|
TEST_F(BufferValidationTest, GetMappedRangeOnUnmappedBuffer) {
|
||||||
|
// Unmapped at creation case.
|
||||||
|
{
|
||||||
|
wgpu::BufferDescriptor desc;
|
||||||
|
desc.size = 4;
|
||||||
|
desc.usage = wgpu::BufferUsage::CopySrc;
|
||||||
|
wgpu::Buffer buf = device.CreateBuffer(&desc);
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmapped after CreateBufferMapped case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateBufferMapped(4, wgpu::BufferUsage::CopySrc).buffer;
|
||||||
|
buf.Unmap();
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmapped after MapReadAsync case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateMapReadBuffer(4);
|
||||||
|
|
||||||
|
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
|
||||||
|
EXPECT_CALL(*mockBufferMapReadCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
|
||||||
|
.Times(1);
|
||||||
|
queue.Submit(0, nullptr);
|
||||||
|
buf.Unmap();
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmapped after MapWriteAsync case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateMapWriteBuffer(4);
|
||||||
|
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
|
||||||
|
EXPECT_CALL(*mockBufferMapWriteCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
|
||||||
|
.Times(1);
|
||||||
|
queue.Submit(0, nullptr);
|
||||||
|
buf.Unmap();
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that it is invalid to call GetMappedRange on a destroyed buffer.
|
||||||
|
TEST_F(BufferValidationTest, GetMappedRangeOnDestroyedBuffer) {
|
||||||
|
// Destroyed after creation case.
|
||||||
|
{
|
||||||
|
wgpu::BufferDescriptor desc;
|
||||||
|
desc.size = 4;
|
||||||
|
desc.usage = wgpu::BufferUsage::CopySrc;
|
||||||
|
wgpu::Buffer buf = device.CreateBuffer(&desc);
|
||||||
|
buf.Destroy();
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroyed after CreateBufferMapped case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateBufferMapped(4, wgpu::BufferUsage::CopySrc).buffer;
|
||||||
|
buf.Destroy();
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroyed after MapReadAsync case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateMapReadBuffer(4);
|
||||||
|
|
||||||
|
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
|
||||||
|
EXPECT_CALL(*mockBufferMapReadCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
|
||||||
|
.Times(1);
|
||||||
|
queue.Submit(0, nullptr);
|
||||||
|
buf.Destroy();
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroyed after MapWriteAsync case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateMapWriteBuffer(4);
|
||||||
|
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
|
||||||
|
EXPECT_CALL(*mockBufferMapWriteCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
|
||||||
|
.Times(1);
|
||||||
|
queue.Submit(0, nullptr);
|
||||||
|
buf.Destroy();
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetConstMappedRange()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that it is invalid to call GetMappedRange on a buffer afterMapReadAsync
|
||||||
|
TEST_F(BufferValidationTest, GetMappedRangeOnMappedForReading) {
|
||||||
|
wgpu::Buffer buf = CreateMapReadBuffer(4);
|
||||||
|
|
||||||
|
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
|
||||||
|
EXPECT_CALL(*mockBufferMapReadCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
|
||||||
|
.Times(1);
|
||||||
|
queue.Submit(0, nullptr);
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(ASSERT_EQ(nullptr, buf.GetMappedRange()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test valid cases to call GetMappedRange on a buffer.
|
||||||
|
TEST_F(BufferValidationTest, GetMappedRangeValidCases) {
|
||||||
|
// GetMappedRange after CreateBufferMapped case.
|
||||||
|
{
|
||||||
|
wgpu::CreateBufferMappedResult result = CreateBufferMapped(4, wgpu::BufferUsage::CopySrc);
|
||||||
|
ASSERT_NE(result.buffer.GetConstMappedRange(), nullptr);
|
||||||
|
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.buffer.GetMappedRange());
|
||||||
|
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMappedRange after MapReadAsync case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateMapReadBuffer(4);
|
||||||
|
|
||||||
|
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
|
||||||
|
|
||||||
|
const void* mappedPointer = nullptr;
|
||||||
|
EXPECT_CALL(*mockBufferMapReadCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
|
||||||
|
.WillOnce(SaveArg<1>(&mappedPointer));
|
||||||
|
|
||||||
|
queue.Submit(0, nullptr);
|
||||||
|
|
||||||
|
ASSERT_NE(buf.GetConstMappedRange(), nullptr);
|
||||||
|
ASSERT_EQ(buf.GetConstMappedRange(), mappedPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMappedRange after MapWriteAsync case.
|
||||||
|
{
|
||||||
|
wgpu::Buffer buf = CreateMapWriteBuffer(4);
|
||||||
|
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
|
||||||
|
|
||||||
|
const void* mappedPointer = nullptr;
|
||||||
|
EXPECT_CALL(*mockBufferMapWriteCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
|
||||||
|
.WillOnce(SaveArg<1>(&mappedPointer));
|
||||||
|
|
||||||
|
queue.Submit(0, nullptr);
|
||||||
|
|
||||||
|
ASSERT_NE(buf.GetConstMappedRange(), nullptr);
|
||||||
|
ASSERT_EQ(buf.GetConstMappedRange(), buf.GetMappedRange());
|
||||||
|
ASSERT_EQ(buf.GetConstMappedRange(), mappedPointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue