Implement GPUBufferDescriptor.mappedAtCreation.

This CL:

 - Adds mappedAtCreation to dawn.json
 - Changes dawn_native to implement CreateBufferMapped in terms of
   mappedAtCreation.
 - Duplicates all the CreateBufferMappedTests to mappedAtCreation tests
   (both validation and end2end).
 - Implements dawn_wire's mappedAtCreation in terms of
   CreateBufferMapped. The reversal in dawn_wire will be done in a
   follow-up CL.

Bug: dawn:445

Change-Id: I70b9fa729b1402524a6b993c3f288987eb65c6c4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24083
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Corentin Wallez
2020-07-07 11:21:51 +00:00
committed by Commit Bot service account
parent cf77d75573
commit b2ea1915d4
20 changed files with 589 additions and 108 deletions

View File

@@ -309,7 +309,6 @@ TEST_P(BufferMapWriteTests, GetMappedRangeZeroSized) {
DAWN_INSTANTIATE_TEST(BufferMapWriteTests, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());
// TODO(enga): These tests should use the testing toggle to initialize resources to 1.
class CreateBufferMappedTests : public DawnTest {
protected:
static void MapReadCallback(WGPUBufferMapAsyncStatus status,
@@ -594,6 +593,273 @@ DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
OpenGLBackend(),
VulkanBackend());
class BufferMappedAtCreationTests : public DawnTest {
protected:
static void MapReadCallback(WGPUBufferMapAsyncStatus status,
const void* data,
uint64_t,
void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
static_cast<BufferMappedAtCreationTests*>(userdata)->mappedData = data;
}
const void* MapReadAsyncAndWait(const wgpu::Buffer& buffer) {
buffer.MapReadAsync(MapReadCallback, this);
while (mappedData == nullptr) {
WaitABit();
}
return mappedData;
}
void UnmapBuffer(const wgpu::Buffer& buffer) {
buffer.Unmap();
mappedData = nullptr;
}
wgpu::Buffer BufferMappedAtCreation(wgpu::BufferUsage usage, uint64_t size) {
wgpu::BufferDescriptor descriptor;
descriptor.size = size;
descriptor.usage = usage;
descriptor.mappedAtCreation = true;
return device.CreateBuffer(&descriptor);
}
wgpu::Buffer BufferMappedAtCreationWithData(wgpu::BufferUsage usage,
const std::vector<uint32_t>& data) {
size_t byteLength = data.size() * sizeof(uint32_t);
wgpu::Buffer buffer = BufferMappedAtCreation(usage, byteLength);
memcpy(buffer.GetMappedRange(), data.data(), byteLength);
return buffer;
}
private:
const void* mappedData = nullptr;
};
// Test that the simplest mappedAtCreation works for MapWrite buffers.
TEST_P(BufferMappedAtCreationTests, MapWriteUsageSmall) {
uint32_t myData = 230502;
wgpu::Buffer buffer = BufferMappedAtCreationWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}
// Test that the simplest mappedAtCreation works for MapRead buffers.
TEST_P(BufferMappedAtCreationTests, MapReadUsageSmall) {
uint32_t myData = 230502;
wgpu::Buffer buffer = BufferMappedAtCreationWithData(wgpu::BufferUsage::MapRead, {myData});
UnmapBuffer(buffer);
const void* mappedData = MapReadAsyncAndWait(buffer);
ASSERT_EQ(myData, *reinterpret_cast<const uint32_t*>(mappedData));
UnmapBuffer(buffer);
}
// Test that the simplest mappedAtCreation works for non-mappable buffers.
TEST_P(BufferMappedAtCreationTests, NonMappableUsageSmall) {
uint32_t myData = 4239;
wgpu::Buffer buffer = BufferMappedAtCreationWithData(wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}
// Test mappedAtCreation for a large MapWrite buffer
TEST_P(BufferMappedAtCreationTests, MapWriteUsageLarge) {
constexpr uint64_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::Buffer buffer = BufferMappedAtCreationWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffer, 0, kDataSize);
}
// Test mappedAtCreation for a large MapRead buffer
TEST_P(BufferMappedAtCreationTests, MapReadUsageLarge) {
constexpr uint64_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::Buffer buffer = BufferMappedAtCreationWithData(wgpu::BufferUsage::MapRead, myData);
UnmapBuffer(buffer);
const void* mappedData = MapReadAsyncAndWait(buffer);
ASSERT_EQ(0, memcmp(mappedData, myData.data(), kDataSize * sizeof(uint32_t)));
UnmapBuffer(buffer);
}
// Test mappedAtCreation for a large non-mappable buffer
TEST_P(BufferMappedAtCreationTests, NonMappableUsageLarge) {
constexpr uint64_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::Buffer buffer = BufferMappedAtCreationWithData(wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffer, 0, kDataSize);
}
// Test destroying a non-mappable buffer mapped at creation.
// This is a regression test for an issue where the D3D12 backend thought the buffer was actually
// mapped and tried to unlock the heap residency (when actually the buffer was using a staging
// buffer)
TEST_P(BufferMappedAtCreationTests, DestroyNonMappableWhileMappedForCreation) {
wgpu::Buffer buffer = BufferMappedAtCreation(wgpu::BufferUsage::CopySrc, 4);
buffer.Destroy();
}
// Test destroying a mappable buffer mapped at creation.
TEST_P(BufferMappedAtCreationTests, DestroyMappableWhileMappedForCreation) {
wgpu::Buffer buffer = BufferMappedAtCreation(wgpu::BufferUsage::MapRead, 4);
buffer.Destroy();
}
// Test that mapping a buffer is valid after mappedAtCreation and Unmap
TEST_P(BufferMappedAtCreationTests, CreateThenMapSuccess) {
static uint32_t myData = 230502;
static uint32_t myData2 = 1337;
wgpu::Buffer buffer = BufferMappedAtCreationWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
bool done = false;
buffer.MapWriteAsync(
[](WGPUBufferMapAsyncStatus status, void* data, uint64_t, void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
*static_cast<uint32_t*>(data) = myData2;
*static_cast<bool*>(userdata) = true;
},
&done);
while (!done) {
WaitABit();
}
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData2, buffer, 0);
}
// Test that is is invalid to map a buffer twice when using mappedAtCreation
TEST_P(BufferMappedAtCreationTests, CreateThenMapBeforeUnmapFailure) {
uint32_t myData = 230502;
wgpu::Buffer buffer = BufferMappedAtCreationWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
ASSERT_DEVICE_ERROR([&]() {
bool done = false;
buffer.MapWriteAsync(
[](WGPUBufferMapAsyncStatus status, void* data, uint64_t, void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Error, status);
ASSERT_EQ(nullptr, data);
*static_cast<bool*>(userdata) = true;
},
&done);
while (!done) {
WaitABit();
}
}());
// mappedAtCreation is unaffected by the MapWrite error.
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}
// Test that creating a zero-sized buffer mapped is allowed.
TEST_P(BufferMappedAtCreationTests, ZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::Vertex;
descriptor.mappedAtCreation = true;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
ASSERT_NE(nullptr, buffer.GetMappedRange());
// Check that unmapping the buffer works too.
UnmapBuffer(buffer);
}
// Test that creating a zero-sized mapppable buffer mapped. (it is a different code path)
TEST_P(BufferMappedAtCreationTests, ZeroSizedMappableBuffer) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapWrite;
descriptor.mappedAtCreation = true;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
ASSERT_NE(nullptr, buffer.GetMappedRange());
// Check that unmapping the buffer works too.
UnmapBuffer(buffer);
}
// Test that creating a zero-sized error buffer mapped. (it is a different code path)
TEST_P(BufferMappedAtCreationTests, ZeroSizedErrorBuffer) {
DAWN_SKIP_TEST_IF(IsDawnValidationSkipped());
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Storage;
descriptor.mappedAtCreation = true;
wgpu::Buffer buffer;
ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&descriptor));
ASSERT_NE(nullptr, buffer.GetMappedRange());
}
// Test the result of GetMappedRange when mapped at creation.
TEST_P(BufferMappedAtCreationTests, GetMappedRange) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopyDst;
descriptor.mappedAtCreation = true;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
ASSERT_EQ(buffer.GetMappedRange(), buffer.GetConstMappedRange());
ASSERT_NE(buffer.GetMappedRange(), nullptr);
buffer.Unmap();
}
// Test the result of GetMappedRange when mapped at creation for a zero-sized buffer.
TEST_P(BufferMappedAtCreationTests, GetMappedRangeZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::CopyDst;
descriptor.mappedAtCreation = true;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
ASSERT_EQ(buffer.GetMappedRange(), buffer.GetConstMappedRange());
ASSERT_NE(buffer.GetMappedRange(), nullptr);
buffer.Unmap();
}
DAWN_INSTANTIATE_TEST(BufferMappedAtCreationTests,
D3D12Backend(),
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
MetalBackend(),
OpenGLBackend(),
VulkanBackend());
class BufferTests : public DawnTest {};
// Test that creating a zero-buffer is allowed.
@@ -664,6 +930,51 @@ TEST_P(BufferTests, CreateBufferMappedOOM) {
}
}
// Test that a very large buffer mappedAtCreation fails gracefully.
TEST_P(BufferTests, BufferMappedAtCreationOOM) {
// TODO(http://crbug.com/dawn/27): Missing support.
DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsAsan());
// Test non-mappable buffer
{
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopyDst;
descriptor.mappedAtCreation = true;
// Control: test a small buffer works.
device.CreateBuffer(&descriptor);
// Test an enormous buffer fails
descriptor.size = std::numeric_limits<uint64_t>::max();
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
descriptor.size = 1ull << 50;
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
}
// Test mappable buffer
{
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
descriptor.mappedAtCreation = true;
// Control: test a small buffer works.
device.CreateBuffer(&descriptor);
// Test an enormous buffer fails
descriptor.size = std::numeric_limits<uint64_t>::max();
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
descriptor.size = 1ull << 50;
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
}
}
// Test that mapping an OOM buffer for reading fails gracefully
TEST_P(BufferTests, CreateBufferOOMMapReadAsync) {
// TODO(http://crbug.com/dawn/27): Missing support.

View File

@@ -295,6 +295,17 @@ TEST_P(DeviceLostTest, CreateBufferMappedFails) {
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&bufferDescriptor));
}
// Test that mappedAtCreation fails after device is lost
TEST_P(DeviceLostTest, CreateBufferMappedAtCreationFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
bufferDescriptor.mappedAtCreation = true;
SetCallbackAndLoseForTesting();
ASSERT_DEVICE_ERROR(device.CreateBuffer(&bufferDescriptor));
}
// Test that BufferMapReadAsync fails after device is lost
TEST_P(DeviceLostTest, BufferMapReadAsyncFails) {
wgpu::BufferDescriptor bufferDescriptor;
@@ -333,9 +344,7 @@ TEST_P(DeviceLostTest, WriteBufferFails) {
}
// Test it's possible to GetMappedRange on a buffer created mapped after device loss
// TODO(cwallez@chromium.org): enable after CreateBufferMapped is implemented in terms of
// mappedAtCreation.
TEST_P(DeviceLostTest, DISABLED_GetMappedRange_CreateBufferMappedAfterLoss) {
TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAfterLoss) {
SetCallbackAndLoseForTesting();
wgpu::BufferDescriptor desc;
@@ -362,6 +371,34 @@ TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedBeforeLoss) {
ASSERT_EQ(result.buffer.GetMappedRange(), result.data);
}
// Test it's possible to GetMappedRange on a buffer created mapped after device loss
TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAtCreationAfterLoss) {
SetCallbackAndLoseForTesting();
wgpu::BufferDescriptor desc;
desc.size = 4;
desc.usage = wgpu::BufferUsage::CopySrc;
desc.mappedAtCreation = true;
ASSERT_DEVICE_ERROR(wgpu::Buffer buffer = device.CreateBuffer(&desc));
ASSERT_NE(buffer.GetMappedRange(), nullptr);
}
// Test that device loss doesn't change the result of GetMappedRange, mappedAtCreation version.
TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAtCreationBeforeLoss) {
wgpu::BufferDescriptor desc;
desc.size = 4;
desc.usage = wgpu::BufferUsage::CopySrc;
desc.mappedAtCreation = true;
wgpu::Buffer buffer = device.CreateBuffer(&desc);
void* rangeBeforeLoss = buffer.GetMappedRange();
SetCallbackAndLoseForTesting();
ASSERT_NE(buffer.GetMappedRange(), nullptr);
ASSERT_EQ(buffer.GetMappedRange(), rangeBeforeLoss);
}
// Test that device loss doesn't change the result of GetMappedRange, mapReadAsync version.
TEST_P(DeviceLostTest, GetMappedRange_MapReadAsync) {
wgpu::BufferDescriptor desc;

View File

@@ -83,6 +83,15 @@ class BufferValidationTest : public ValidationTest {
return device.CreateBufferMapped(&descriptor);
}
wgpu::Buffer BufferMappedAtCreation(uint64_t size, wgpu::BufferUsage usage) {
wgpu::BufferDescriptor descriptor;
descriptor.size = size;
descriptor.usage = usage;
descriptor.mappedAtCreation = true;
return device.CreateBuffer(&descriptor);
}
wgpu::Queue queue;
private:
@@ -198,6 +207,21 @@ TEST_F(BufferValidationTest, NonMappableCreateBufferMappedSuccess) {
result.buffer.Unmap();
}
// Test the success case for mappedAtCreation
TEST_F(BufferValidationTest, MappedAtCreationSuccess) {
BufferMappedAtCreation(4, wgpu::BufferUsage::MapWrite);
}
// Test the success case for mappedAtCreation for a non-mappable usage
TEST_F(BufferValidationTest, NonMappableMappedAtCreationSuccess) {
BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
}
// Test there is an error when mappedAtCreation is set but the size isn't aligned to 4.
TEST_F(BufferValidationTest, MappedAtCreationSizeAlignment) {
ASSERT_DEVICE_ERROR(BufferMappedAtCreation(2, wgpu::BufferUsage::MapWrite));
}
// Test map reading a buffer with wrong current usage
TEST_F(BufferValidationTest, MapReadWrongUsage) {
wgpu::BufferDescriptor descriptor;
@@ -537,6 +561,20 @@ TEST_F(BufferValidationTest, MapCreateBufferMappedBuffer) {
}
}
// Test that is is invalid to Map a buffer mapped at creation.
TEST_F(BufferValidationTest, MapBufferMappedAtCreation) {
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::MapRead);
ASSERT_DEVICE_ERROR(buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr));
queue.Submit(0, nullptr);
}
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::MapWrite);
ASSERT_DEVICE_ERROR(buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr));
queue.Submit(0, nullptr);
}
}
// Test that it is valid to submit a buffer in a queue with a map usage if it is unmapped
TEST_F(BufferValidationTest, SubmitBufferWithMapUsage) {
wgpu::BufferDescriptor descriptorA;
@@ -603,6 +641,30 @@ TEST_F(BufferValidationTest, SubmitMappedBuffer) {
wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
wgpu::Buffer bufB = device.CreateBufferMapped(&descriptorB).buffer;
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
queue.Submit(0, nullptr);
}
{
wgpu::BufferDescriptor mappedBufferDesc = descriptorA;
mappedBufferDesc.mappedAtCreation = true;
wgpu::Buffer bufA = device.CreateBuffer(&mappedBufferDesc);
wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
queue.Submit(0, nullptr);
}
{
wgpu::BufferDescriptor mappedBufferDesc = descriptorB;
mappedBufferDesc.mappedAtCreation = true;
wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
wgpu::Buffer bufB = device.CreateBuffer(&mappedBufferDesc);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
@@ -685,6 +747,15 @@ TEST_F(BufferValidationTest, GetMappedRangeOnUnmappedBuffer) {
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Unmapped after mappedAtCreation case.
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
buf.Unmap();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Unmapped after MapReadAsync case.
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
@@ -738,6 +809,15 @@ TEST_F(BufferValidationTest, GetMappedRangeOnDestroyedBuffer) {
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Destroyed after mappedAtCreation case.
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
buf.Destroy();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Destroyed after MapReadAsync case.
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
@@ -791,6 +871,13 @@ TEST_F(BufferValidationTest, GetMappedRangeValidCases) {
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
}
// GetMappedRange after mappedAtCreation case.
{
wgpu::Buffer buffer = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(buffer.GetConstMappedRange(), buffer.GetMappedRange());
}
// GetMappedRange after MapReadAsync case.
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
@@ -827,13 +914,25 @@ TEST_F(BufferValidationTest, GetMappedRangeValidCases) {
}
// Test valid cases to call GetMappedRange on an error buffer.
// TODO(cwallez@chromium.org): enable after CreateBufferMapped is implemented in terms of
// mappedAtCreation.
TEST_F(BufferValidationTest, DISABLED_GetMappedRangeOnErrorBuffer) {
TEST_F(BufferValidationTest, GetMappedRangeOnErrorBuffer) {
wgpu::BufferDescriptor desc;
desc.size = 4;
desc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead;
uint64_t kStupidLarge = uint64_t(1) << uint64_t(63);
// GetMappedRange after CreateBufferMapped a zero-sized buffer returns a non-nullptr.
// This is to check we don't do a malloc(0).
{
wgpu::CreateBufferMappedResult result;
ASSERT_DEVICE_ERROR(result = CreateBufferMapped(
0, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));
ASSERT_NE(result.buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.buffer.GetMappedRange());
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
}
// GetMappedRange after CreateBufferMapped non-OOM returns a non-nullptr.
{
wgpu::CreateBufferMappedResult result;
@@ -848,11 +947,44 @@ TEST_F(BufferValidationTest, DISABLED_GetMappedRangeOnErrorBuffer) {
// GetMappedRange after CreateBufferMapped OOM case returns nullptr.
{
wgpu::CreateBufferMappedResult result;
ASSERT_DEVICE_ERROR(result = CreateBufferMapped(
1 << 31, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));
ASSERT_DEVICE_ERROR(result =
CreateBufferMapped(kStupidLarge, wgpu::BufferUsage::Storage |
wgpu::BufferUsage::MapRead));
ASSERT_EQ(result.buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.buffer.GetMappedRange());
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
}
// GetMappedRange after mappedAtCreation a zero-sized buffer returns a non-nullptr.
// This is to check we don't do a malloc(0).
{
wgpu::Buffer buffer;
ASSERT_DEVICE_ERROR(buffer = BufferMappedAtCreation(
0, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));
ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(buffer.GetConstMappedRange(), buffer.GetMappedRange());
}
// GetMappedRange after mappedAtCreation non-OOM returns a non-nullptr.
{
wgpu::Buffer buffer;
ASSERT_DEVICE_ERROR(buffer = BufferMappedAtCreation(
4, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));
ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(buffer.GetConstMappedRange(), buffer.GetMappedRange());
}
// GetMappedRange after mappedAtCreation OOM case returns nullptr.
{
wgpu::Buffer buffer;
ASSERT_DEVICE_ERROR(
buffer = BufferMappedAtCreation(
kStupidLarge, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));
ASSERT_EQ(buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(buffer.GetConstMappedRange(), buffer.GetMappedRange());
}
}

View File

@@ -162,6 +162,18 @@ TEST_F(QueueWriteBufferValidationTest, MappedBuffer) {
ASSERT_DEVICE_ERROR(queue.WriteBuffer(result.buffer, 0, &value, sizeof(value)));
}
// mappedAtCreation
{
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopyDst;
descriptor.mappedAtCreation = true;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
uint32_t value = 0;
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buffer, 0, &value, sizeof(value)));
}
// MapReadAsync
{
wgpu::BufferDescriptor descriptor;