Implement CreateBufferMapped in dawn_native for MAP_WRITE buffers only.

This is the first command to return a struct. This patch also
updates the code generator to support structure return values.

Bug: dawn:7
Change-Id: Ie8acec895c0ec88429672138ffc900032fbbc447
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/4780
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2019-05-15 18:55:22 +00:00 committed by Commit Bot service account
parent 0195dbf908
commit 740995c0b1
22 changed files with 241 additions and 12 deletions

View File

@ -213,6 +213,14 @@
"char": { "char": {
"category": "native" "category": "native"
}, },
"create buffer mapped result": {
"category": "structure",
"members": [
{"name": "buffer", "type": "buffer"},
{"name": "data length", "type": "uint64_t"},
{"name": "data", "type": "uint8_t", "annotation": "*", "length": "data length"}
]
},
"color": { "color": {
"category": "structure", "category": "structure",
"members": [ "members": [
@ -410,6 +418,13 @@
{"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"} {"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"}
] ]
}, },
{
"name": "create buffer mapped",
"returns": "create buffer mapped result",
"args": [
{"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"}
]
},
{ {
"name": "create command encoder", "name": "create command encoder",
"returns": "command encoder" "returns": "command encoder"

View File

@ -58,6 +58,7 @@
], ],
"client_handwritten_commands": [ "client_handwritten_commands": [
"BufferUnmap", "BufferUnmap",
"DeviceCreateBufferMapped",
"QueueCreateFence", "QueueCreateFence",
"FenceGetCompletedValue", "FenceGetCompletedValue",
"QueueSignal" "QueueSignal"

View File

@ -230,9 +230,34 @@ def as_cppType(name):
else: else:
return name.CamelCase() return name.CamelCase()
def convert_cType_to_cppType(typ, annotation, arg, indent=0):
if typ.category == 'native':
return arg
if annotation == 'value':
if typ.category == 'object':
return '{}::Acquire({})'.format(as_cppType(typ.name), arg)
elif typ.category == 'structure':
converted_members = [
convert_cType_to_cppType(
member.type, member.annotation,
'{}.{}'.format(arg, as_varName(member.name)),
indent + 1)
for member in typ.members]
converted_members = [(' ' * 4) + m for m in converted_members ]
converted_members = ',\n'.join(converted_members)
return as_cppType(typ.name) + ' {\n' + converted_members + '\n}'
else:
return 'static_cast<{}>({})'.format(as_cppType(typ.name), arg)
else:
return 'reinterpret_cast<{} {}>({})'.format(as_cppType(typ.name), annotation, arg)
def decorate(name, typ, arg): def decorate(name, typ, arg):
if arg.annotation == 'value': if arg.annotation == 'value':
return typ + ' ' + name return typ + ' ' + name
elif arg.annotation == '*':
return typ + ' * ' + name
elif arg.annotation == 'const*': elif arg.annotation == 'const*':
return typ + ' const * ' + name return typ + ' const * ' + name
elif arg.annotation == 'const*const*': elif arg.annotation == 'const*const*':
@ -314,6 +339,7 @@ def get_renders_for_targets(api_params, wire_json, targets):
'as_cProc': as_cProc, 'as_cProc': as_cProc,
'as_cType': as_cType, 'as_cType': as_cType,
'as_cppType': as_cppType, 'as_cppType': as_cppType,
'convert_cType_to_cppType': convert_cType_to_cppType,
'as_varName': as_varName, 'as_varName': as_varName,
'decorate': decorate, 'decorate': decorate,
} }

View File

@ -96,13 +96,7 @@ namespace dawn {
{{render_cpp_to_c_method_call(type, method)}}; {{render_cpp_to_c_method_call(type, method)}};
{% else %} {% else %}
auto result = {{render_cpp_to_c_method_call(type, method)}}; auto result = {{render_cpp_to_c_method_call(type, method)}};
{% if method.return_type.category == "native" %} return {{convert_cType_to_cppType(method.return_type, 'value', 'result') | indent(8)}};
return result;
{% elif method.return_type.category == "object" %}
return {{as_cppType(method.return_type.name)}}::Acquire(result);
{% else %}
return static_cast<{{as_cppType(method.return_type.name)}}>(result);
{% endif%}
{% endif %} {% endif %}
} }
{% endfor %} {% endfor %}

View File

@ -152,7 +152,7 @@
//* Serializes `record` into `transfer`, using `buffer` to get more space for pointed-to data //* Serializes `record` into `transfer`, using `buffer` to get more space for pointed-to data
//* and `provider` to serialize objects. //* and `provider` to serialize objects.
void {{Return}}{{name}}Serialize(const {{Return}}{{name}}{{Cmd}}& record, {{Return}}{{name}}Transfer* transfer, DAWN_DECLARE_UNUSED void {{Return}}{{name}}Serialize(const {{Return}}{{name}}{{Cmd}}& record, {{Return}}{{name}}Transfer* transfer,
char** buffer char** buffer
{%- if record.has_dawn_object -%} {%- if record.has_dawn_object -%}
, const ObjectIdProvider& provider , const ObjectIdProvider& provider
@ -200,11 +200,12 @@
} }
{% endfor %} {% endfor %}
} }
DAWN_UNUSED_FUNC({{Return}}{{name}}Serialize);
//* Deserializes `transfer` into `record` getting more serialized data from `buffer` and `size` //* Deserializes `transfer` into `record` getting more serialized data from `buffer` and `size`
//* if needed, using `allocator` to store pointed-to values and `resolver` to translate object //* if needed, using `allocator` to store pointed-to values and `resolver` to translate object
//* Ids to actual objects. //* Ids to actual objects.
DeserializeResult {{Return}}{{name}}Deserialize({{Return}}{{name}}{{Cmd}}* record, const {{Return}}{{name}}Transfer* transfer, DAWN_DECLARE_UNUSED DeserializeResult {{Return}}{{name}}Deserialize({{Return}}{{name}}{{Cmd}}* record, const {{Return}}{{name}}Transfer* transfer,
const char** buffer, size_t* size, DeserializeAllocator* allocator const char** buffer, size_t* size, DeserializeAllocator* allocator
{%- if record.has_dawn_object -%} {%- if record.has_dawn_object -%}
, const ObjectIdResolver& resolver , const ObjectIdResolver& resolver
@ -283,6 +284,7 @@
return DeserializeResult::Success; return DeserializeResult::Success;
} }
DAWN_UNUSED_FUNC({{Return}}{{name}}Deserialize);
{% endmacro %} {% endmacro %}
{% macro write_command_serialization_methods(command, is_return) %} {% macro write_command_serialization_methods(command, is_return) %}

View File

@ -31,7 +31,24 @@ namespace dawn_native {
ErrorBuffer(DeviceBase* device) : BufferBase(device, ObjectBase::kError) { ErrorBuffer(DeviceBase* device) : BufferBase(device, ObjectBase::kError) {
} }
static ErrorBuffer* MakeMapped(DeviceBase* device,
uint64_t size,
uint8_t** mappedPointer) {
ASSERT(mappedPointer != nullptr);
ErrorBuffer* buffer = new ErrorBuffer(device);
buffer->mFakeMappedData = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
*mappedPointer = buffer->mFakeMappedData.get();
return buffer;
}
private: private:
MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override {
UNREACHABLE();
return {};
}
MaybeError SetSubDataImpl(uint32_t start, MaybeError SetSubDataImpl(uint32_t start,
uint32_t count, uint32_t count,
const uint8_t* data) override { const uint8_t* data) override {
@ -45,11 +62,14 @@ namespace dawn_native {
UNREACHABLE(); UNREACHABLE();
} }
void UnmapImpl() override { void UnmapImpl() override {
UNREACHABLE(); ASSERT(mFakeMappedData);
mFakeMappedData.reset();
} }
void DestroyImpl() override { void DestroyImpl() override {
UNREACHABLE(); UNREACHABLE();
} }
std::unique_ptr<uint8_t[]> mFakeMappedData;
}; };
} // anonymous namespace } // anonymous namespace
@ -104,6 +124,13 @@ namespace dawn_native {
return new ErrorBuffer(device); return new ErrorBuffer(device);
} }
// static
BufferBase* BufferBase::MakeErrorMapped(DeviceBase* device,
uint64_t size,
uint8_t** mappedPointer) {
return ErrorBuffer::MakeMapped(device, size, mappedPointer);
}
uint32_t BufferBase::GetSize() const { uint32_t BufferBase::GetSize() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mSize; return mSize;
@ -114,6 +141,22 @@ namespace dawn_native {
return mUsage; return mUsage;
} }
MaybeError BufferBase::MapAtCreation(uint8_t** mappedPointer) {
ASSERT(!IsError());
ASSERT(mappedPointer != nullptr);
mState = BufferState::Mapped;
if ((mUsage & dawn::BufferUsageBit::MapWrite) == 0) {
// TODO(enga): Support non-mappable buffers with a staging buffer.
return DAWN_VALIDATION_ERROR("MapWrite usage required");
}
DAWN_TRY(MapAtCreationImpl(mappedPointer));
ASSERT(*mappedPointer != nullptr);
return {};
}
MaybeError BufferBase::ValidateCanUseInSubmitNow() const { MaybeError BufferBase::ValidateCanUseInSubmitNow() const {
ASSERT(!IsError()); ASSERT(!IsError());
@ -239,6 +282,11 @@ namespace dawn_native {
} }
void BufferBase::Unmap() { void BufferBase::Unmap() {
if (IsError()) {
// It is an error to call Unmap() on an ErrorBuffer, but we still need to reclaim the
// fake mapped staging data.
UnmapImpl();
}
if (GetDevice()->ConsumedError(ValidateUnmap())) { if (GetDevice()->ConsumedError(ValidateUnmap())) {
return; return;
} }

View File

@ -45,10 +45,15 @@ namespace dawn_native {
~BufferBase(); ~BufferBase();
static BufferBase* MakeError(DeviceBase* device); static BufferBase* MakeError(DeviceBase* device);
static BufferBase* MakeErrorMapped(DeviceBase* device,
uint64_t size,
uint8_t** mappedPointer);
uint32_t GetSize() const; uint32_t GetSize() const;
dawn::BufferUsageBit GetUsage() const; dawn::BufferUsageBit GetUsage() const;
MaybeError MapAtCreation(uint8_t** mappedPointer);
MaybeError ValidateCanUseInSubmitNow() const; MaybeError ValidateCanUseInSubmitNow() const;
// Dawn API // Dawn API
@ -73,6 +78,7 @@ namespace dawn_native {
void DestroyInternal(); void DestroyInternal();
private: private:
virtual MaybeError MapAtCreationImpl(uint8_t** mappedPointer) = 0;
virtual MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data); virtual MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data);
virtual void MapReadAsyncImpl(uint32_t serial) = 0; virtual void MapReadAsyncImpl(uint32_t serial) = 0;
virtual void MapWriteAsyncImpl(uint32_t serial) = 0; virtual void MapWriteAsyncImpl(uint32_t serial) = 0;

View File

@ -237,6 +237,30 @@ namespace dawn_native {
return result; return result;
} }
DawnCreateBufferMappedResult DeviceBase::CreateBufferMapped(
const BufferDescriptor* descriptor) {
BufferBase* buffer = nullptr;
uint8_t* data = nullptr;
if (ConsumedError(CreateBufferInternal(&buffer, descriptor)) ||
ConsumedError(buffer->MapAtCreation(&data))) {
// Map failed. Replace the buffer with an error buffer.
if (buffer != nullptr) {
delete buffer;
}
buffer = BufferBase::MakeErrorMapped(this, descriptor->size, &data);
}
ASSERT(buffer != nullptr);
ASSERT(data != nullptr);
DawnCreateBufferMappedResult result = {};
result.buffer = reinterpret_cast<DawnBuffer>(buffer);
result.data = data;
result.dataLength = descriptor->size;
return result;
}
CommandEncoderBase* DeviceBase::CreateCommandEncoder() { CommandEncoderBase* DeviceBase::CreateCommandEncoder() {
return new CommandEncoderBase(this); return new CommandEncoderBase(this);
} }

View File

@ -104,6 +104,7 @@ namespace dawn_native {
BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor); BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor);
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor); BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
BufferBase* CreateBuffer(const BufferDescriptor* descriptor); BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
DawnCreateBufferMappedResult CreateBufferMapped(const BufferDescriptor* descriptor);
CommandEncoderBase* CreateCommandEncoder(); CommandEncoderBase* CreateCommandEncoder();
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor); ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor); PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);

View File

@ -160,6 +160,13 @@ namespace dawn_native { namespace d3d12 {
} }
} }
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
mWrittenMappedRange = {0, GetSize()};
ASSERT_SUCCESS(
mResource->Map(0, &mWrittenMappedRange, reinterpret_cast<void**>(mappedPointer)));
return {};
}
void Buffer::MapReadAsyncImpl(uint32_t serial) { void Buffer::MapReadAsyncImpl(uint32_t serial) {
mWrittenMappedRange = {}; mWrittenMappedRange = {};
D3D12_RANGE readRange = {0, GetSize()}; D3D12_RANGE readRange = {0, GetSize()};

View File

@ -44,6 +44,8 @@ namespace dawn_native { namespace d3d12 {
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
virtual MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
ComPtr<ID3D12Resource> mResource; ComPtr<ID3D12Resource> mResource;
bool mFixedResourceState = false; bool mFixedResourceState = false;
dawn::BufferUsageBit mLastUsage = dawn::BufferUsageBit::None; dawn::BufferUsageBit mLastUsage = dawn::BufferUsageBit::None;

View File

@ -34,11 +34,14 @@ namespace dawn_native { namespace metal {
void OnMapCommandSerialFinished(uint32_t mapSerial, bool isWrite); void OnMapCommandSerialFinished(uint32_t mapSerial, bool isWrite);
private: private:
// Dawn API
void MapReadAsyncImpl(uint32_t serial) override; void MapReadAsyncImpl(uint32_t serial) override;
void MapWriteAsyncImpl(uint32_t serial) override; void MapWriteAsyncImpl(uint32_t serial) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
id<MTLBuffer> mMtlBuffer = nil; id<MTLBuffer> mMtlBuffer = nil;
}; };

View File

@ -47,6 +47,11 @@ namespace dawn_native { namespace metal {
} }
} }
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
*mappedPointer = reinterpret_cast<uint8_t*>([mMtlBuffer contents]);
return {};
}
void Buffer::MapReadAsyncImpl(uint32_t serial) { void Buffer::MapReadAsyncImpl(uint32_t serial) {
MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapTracker(); MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapTracker();
tracker->Track(this, serial, false); tracker->Track(this, serial, false);

View File

@ -184,13 +184,18 @@ namespace dawn_native { namespace null {
: BufferBase(device, descriptor) { : BufferBase(device, descriptor) {
if (GetUsage() & (dawn::BufferUsageBit::TransferDst | dawn::BufferUsageBit::MapRead | if (GetUsage() & (dawn::BufferUsageBit::TransferDst | dawn::BufferUsageBit::MapRead |
dawn::BufferUsageBit::MapWrite)) { dawn::BufferUsageBit::MapWrite)) {
mBackingData = std::unique_ptr<char[]>(new char[GetSize()]); mBackingData = std::unique_ptr<uint8_t[]>(new uint8_t[GetSize()]);
} }
} }
Buffer::~Buffer() { Buffer::~Buffer() {
} }
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
*mappedPointer = mBackingData.get();
return {};
}
void Buffer::MapReadOperationCompleted(uint32_t serial, void* ptr, bool isWrite) { void Buffer::MapReadOperationCompleted(uint32_t serial, void* ptr, bool isWrite) {
if (isWrite) { if (isWrite) {
CallMapWriteCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, ptr, GetSize()); CallMapWriteCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, ptr, GetSize());

View File

@ -138,15 +138,17 @@ namespace dawn_native { namespace null {
void MapReadOperationCompleted(uint32_t serial, void* ptr, bool isWrite); void MapReadOperationCompleted(uint32_t serial, void* ptr, bool isWrite);
private: private:
// Dawn API
MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override;
void MapReadAsyncImpl(uint32_t serial) override; void MapReadAsyncImpl(uint32_t serial) override;
void MapWriteAsyncImpl(uint32_t serial) override; void MapWriteAsyncImpl(uint32_t serial) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
void MapAsyncImplCommon(uint32_t serial, bool isWrite); void MapAsyncImplCommon(uint32_t serial, bool isWrite);
std::unique_ptr<char[]> mBackingData; std::unique_ptr<uint8_t[]> mBackingData;
}; };
class CommandBuffer : public CommandBufferBase { class CommandBuffer : public CommandBufferBase {

View File

@ -35,6 +35,13 @@ namespace dawn_native { namespace opengl {
return mBuffer; return mBuffer;
} }
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
*mappedPointer = reinterpret_cast<uint8_t*>(data);
return {};
}
MaybeError Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { MaybeError Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) {
glBindBuffer(GL_ARRAY_BUFFER, mBuffer); glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferSubData(GL_ARRAY_BUFFER, start, count, data); glBufferSubData(GL_ARRAY_BUFFER, start, count, data);

View File

@ -31,12 +31,15 @@ namespace dawn_native { namespace opengl {
GLuint GetHandle() const; GLuint GetHandle() const;
private: private:
// Dawn API
MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override;
void MapReadAsyncImpl(uint32_t serial) override; void MapReadAsyncImpl(uint32_t serial) override;
void MapWriteAsyncImpl(uint32_t serial) override; void MapWriteAsyncImpl(uint32_t serial) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
GLuint mBuffer = 0; GLuint mBuffer = 0;
}; };

View File

@ -188,6 +188,11 @@ namespace dawn_native { namespace vulkan {
mLastUsage = usage; mLastUsage = usage;
} }
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
*mappedPointer = mMemoryAllocation.GetMappedPointer();
return {};
}
void Buffer::MapReadAsyncImpl(uint32_t serial) { void Buffer::MapReadAsyncImpl(uint32_t serial) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());

View File

@ -41,11 +41,14 @@ namespace dawn_native { namespace vulkan {
void TransitionUsageNow(VkCommandBuffer commands, dawn::BufferUsageBit usage); void TransitionUsageNow(VkCommandBuffer commands, dawn::BufferUsageBit usage);
private: private:
// Dawn API
void MapReadAsyncImpl(uint32_t serial) override; void MapReadAsyncImpl(uint32_t serial) override;
void MapWriteAsyncImpl(uint32_t serial) override; void MapWriteAsyncImpl(uint32_t serial) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
VkBuffer mHandle = VK_NULL_HANDLE; VkBuffer mHandle = VK_NULL_HANDLE;
DeviceMemoryAllocation mMemoryAllocation; DeviceMemoryAllocation mMemoryAllocation;

View File

@ -68,6 +68,14 @@ namespace dawn_wire { namespace client {
cmd.Serialize(allocatedBuffer); cmd.Serialize(allocatedBuffer);
} }
DawnCreateBufferMappedResult ClientDeviceCreateBufferMapped(
DawnDevice cDevice,
const DawnBufferDescriptor* descriptor) {
// TODO(enga): Not implemented
UNREACHABLE();
return {};
}
uint64_t ClientFenceGetCompletedValue(DawnFence cSelf) { uint64_t ClientFenceGetCompletedValue(DawnFence cSelf) {
auto fence = reinterpret_cast<Fence*>(cSelf); auto fence = reinterpret_cast<Fence*>(cSelf);
return fence->completedValue; return fence->completedValue;

View File

@ -229,3 +229,48 @@ DAWN_INSTANTIATE_TEST(BufferSetSubDataTests,
MetalBackend, MetalBackend,
OpenGLBackend, OpenGLBackend,
VulkanBackend); VulkanBackend);
class CreateBufferMappedTests : public DawnTest {};
// Test that the simplest CreateBufferMapped works.
TEST_P(CreateBufferMappedTests, SmallSyncWrite) {
dawn::BufferDescriptor descriptor;
descriptor.nextInChain = nullptr;
descriptor.size = 4;
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
uint32_t myData = 230502;
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
ASSERT_EQ(result.dataLength, descriptor.size);
memcpy(result.data, &myData, sizeof(myData));
result.buffer.Unmap();
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
}
// Test CreateBufferMapped for a large buffer
TEST_P(CreateBufferMappedTests, LargeSyncWrite) {
constexpr uint64_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
dawn::BufferDescriptor descriptor;
descriptor.nextInChain = nullptr;
descriptor.size = static_cast<uint64_t>(kDataSize * sizeof(uint32_t));
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
ASSERT_EQ(result.dataLength, descriptor.size);
memcpy(result.data, myData.data(), kDataSize * sizeof(uint32_t));
result.buffer.Unmap();
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
}
DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
D3D12Backend,
MetalBackend,
OpenGLBackend,
VulkanBackend);

View File

@ -82,6 +82,15 @@ class BufferValidationTest : public ValidationTest {
return device.CreateBuffer(&descriptor); return device.CreateBuffer(&descriptor);
} }
dawn::CreateBufferMappedResult CreateBufferMapped(uint64_t size,
dawn::BufferUsageBit usage) {
dawn::BufferDescriptor descriptor;
descriptor.size = size;
descriptor.usage = usage;
return device.CreateBufferMapped(&descriptor);
}
dawn::Queue queue; dawn::Queue queue;
private: private:
@ -183,6 +192,14 @@ TEST_F(BufferValidationTest, MapWriteSuccess) {
buf.Unmap(); buf.Unmap();
} }
// Test the success case for CreateBufferMapped
TEST_F(BufferValidationTest, CreateBufferMappedSuccess) {
dawn::CreateBufferMappedResult result = CreateBufferMapped(4, dawn::BufferUsageBit::MapWrite);
ASSERT_NE(result.data, nullptr);
ASSERT_EQ(result.dataLength, 4u);
result.buffer.Unmap();
}
// Test map reading a buffer with wrong current usage // Test map reading a buffer with wrong current usage
TEST_F(BufferValidationTest, MapReadWrongUsage) { TEST_F(BufferValidationTest, MapReadWrongUsage) {
dawn::BufferDescriptor descriptor; dawn::BufferDescriptor descriptor;