Add reflection APIs for wgpu::Buffer.
Changes dawn::native procs to correctly convert C++ enum and bitmask returns values. Bug: dawn:1451 Change-Id: I39a8d218f76e25b178a83eeb99d653222d39d040 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/92440 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
faa64a60ef
commit
d428187d35
|
@ -433,6 +433,14 @@
|
|||
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "get usage",
|
||||
"returns": "buffer usage"
|
||||
},
|
||||
{
|
||||
"name": "get size",
|
||||
"returns": "uint64_t"
|
||||
},
|
||||
{
|
||||
"name": "unmap"
|
||||
},
|
||||
|
|
|
@ -189,6 +189,8 @@
|
|||
"BufferMapAsync",
|
||||
"BufferGetConstMappedRange",
|
||||
"BufferGetMappedRange",
|
||||
"BufferGetSize",
|
||||
"BufferGetUsage",
|
||||
"DeviceCreateBuffer",
|
||||
"DeviceCreateComputePipelineAsync",
|
||||
"DeviceCreateRenderPipelineAsync",
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace {{native_namespace}} {
|
|||
{%- endfor -%}
|
||||
);
|
||||
{% if method.return_type.name.canonical_case() != "void" %}
|
||||
{% if method.return_type.category == "object" %}
|
||||
{% if method.return_type.category in ["object", "enum", "bitmask"] %}
|
||||
return ToAPI(result);
|
||||
{% else %}
|
||||
return result;
|
||||
|
@ -104,7 +104,7 @@ namespace {{native_namespace}} {
|
|||
{%- endfor -%}
|
||||
);
|
||||
{% if function.return_type.name.canonical_case() != "void" %}
|
||||
{% if function.return_type.category == "object" %}
|
||||
{% if function.return_type.category in ["object", "enum", "bitmask"] %}
|
||||
return ToAPI(result);
|
||||
{% else %}
|
||||
return result;
|
||||
|
|
|
@ -77,6 +77,16 @@ namespace {{native_namespace}} {
|
|||
static constexpr uint32_t value = {{len(e.values)}};
|
||||
};
|
||||
{% endfor %}
|
||||
|
||||
{% for type in by_category["enum"] + by_category["bitmask"] %}
|
||||
inline {{as_cType(type.name)}} ToAPI({{namespace}}::{{as_cppType(type.name)}} rhs) {
|
||||
return static_cast<{{as_cType(type.name)}}>(rhs);
|
||||
}
|
||||
|
||||
inline {{namespace}}::{{as_cppType(type.name)}} FromAPI({{as_cType(type.name)}} rhs) {
|
||||
return static_cast<{{namespace}}::{{as_cppType(type.name)}}>(rhs);
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
#endif // {{NATIVE_DIR}}_{{PREFIX}}_PLATFORM_AUTOGEN_H_
|
||||
|
|
|
@ -158,7 +158,10 @@ BufferBase::BufferBase(DeviceBase* device, const BufferDescriptor* descriptor)
|
|||
BufferBase::BufferBase(DeviceBase* device,
|
||||
const BufferDescriptor* descriptor,
|
||||
ObjectBase::ErrorTag tag)
|
||||
: ApiObjectBase(device, tag), mSize(descriptor->size), mState(BufferState::Unmapped) {
|
||||
: ApiObjectBase(device, tag),
|
||||
mSize(descriptor->size),
|
||||
mUsage(descriptor->usage),
|
||||
mState(BufferState::Unmapped) {
|
||||
if (descriptor->mappedAtCreation) {
|
||||
mState = BufferState::MappedAtCreation;
|
||||
mMapOffset = 0;
|
||||
|
@ -215,9 +218,14 @@ wgpu::BufferUsage BufferBase::GetUsage() const {
|
|||
}
|
||||
|
||||
wgpu::BufferUsage BufferBase::GetUsageExternalOnly() const {
|
||||
ASSERT(!IsError());
|
||||
return GetUsage() & ~kAllInternalBufferUsages;
|
||||
}
|
||||
|
||||
wgpu::BufferUsage BufferBase::APIGetUsage() const {
|
||||
return mUsage & ~kAllInternalBufferUsages;
|
||||
}
|
||||
|
||||
MaybeError BufferBase::MapAtCreation() {
|
||||
DAWN_TRY(MapAtCreationInternal());
|
||||
|
||||
|
@ -378,6 +386,10 @@ void BufferBase::APIDestroy() {
|
|||
Destroy();
|
||||
}
|
||||
|
||||
uint64_t BufferBase::APIGetSize() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
MaybeError BufferBase::CopyFromStagingBuffer() {
|
||||
ASSERT(mStagingBuffer);
|
||||
if (mSize == 0) {
|
||||
|
|
|
@ -48,8 +48,6 @@ class BufferBase : public ApiObjectBase {
|
|||
MappedAtCreation,
|
||||
Destroyed,
|
||||
};
|
||||
BufferBase(DeviceBase* device, const BufferDescriptor* descriptor);
|
||||
|
||||
static BufferBase* MakeError(DeviceBase* device, const BufferDescriptor* descriptor);
|
||||
|
||||
ObjectType GetType() const override;
|
||||
|
@ -86,12 +84,15 @@ class BufferBase : public ApiObjectBase {
|
|||
const void* APIGetConstMappedRange(size_t offset, size_t size);
|
||||
void APIUnmap();
|
||||
void APIDestroy();
|
||||
wgpu::BufferUsage APIGetUsage() const;
|
||||
uint64_t APIGetSize() const;
|
||||
|
||||
protected:
|
||||
BufferBase(DeviceBase* device, const BufferDescriptor* descriptor);
|
||||
BufferBase(DeviceBase* device, const BufferDescriptor* descriptor, ObjectBase::ErrorTag tag);
|
||||
|
||||
// Constructor used only for mocking and testing.
|
||||
BufferBase(DeviceBase* device, BufferState state);
|
||||
|
||||
void DestroyImpl() override;
|
||||
|
||||
~BufferBase() override;
|
||||
|
|
|
@ -940,3 +940,74 @@ TEST_F(BufferValidationTest, GetMappedRange_OffsetSizeOOB) {
|
|||
EXPECT_EQ(buffer.GetMappedRange(0, 0), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the buffer creation parameters are correctly reflected for succesfully created buffers.
|
||||
TEST_F(BufferValidationTest, CreationParameterReflectionForValidBuffer) {
|
||||
// Test reflection on two succesfully created but different buffers. The reflected data should
|
||||
// be different!
|
||||
{
|
||||
wgpu::BufferDescriptor desc;
|
||||
desc.size = 16;
|
||||
desc.usage = wgpu::BufferUsage::Uniform;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&desc);
|
||||
|
||||
EXPECT_EQ(wgpu::BufferUsage::Uniform, buf.GetUsage());
|
||||
EXPECT_EQ(16u, buf.GetSize());
|
||||
}
|
||||
{
|
||||
wgpu::BufferDescriptor desc;
|
||||
desc.size = 32;
|
||||
desc.usage = wgpu::BufferUsage::Storage;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&desc);
|
||||
|
||||
EXPECT_EQ(wgpu::BufferUsage::Storage, buf.GetUsage());
|
||||
EXPECT_EQ(32u, buf.GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the buffer creation parameters are correctly reflected for buffers invalid because of
|
||||
// validation errors.
|
||||
TEST_F(BufferValidationTest, CreationParameterReflectionForErrorBuffer) {
|
||||
wgpu::BufferDescriptor desc;
|
||||
desc.usage = wgpu::BufferUsage::Uniform;
|
||||
desc.size = 19;
|
||||
desc.mappedAtCreation = true;
|
||||
|
||||
// Error! MappedAtCreation requires size % 4 == 0.
|
||||
wgpu::Buffer buf;
|
||||
ASSERT_DEVICE_ERROR(buf = device.CreateBuffer(&desc));
|
||||
|
||||
// Reflection data is still exactly what was in the descriptor.
|
||||
EXPECT_EQ(wgpu::BufferUsage::Uniform, buf.GetUsage());
|
||||
EXPECT_EQ(19u, buf.GetSize());
|
||||
}
|
||||
|
||||
// Test that the buffer creation parameters are correctly reflected for buffers invalid because of
|
||||
// OOM.
|
||||
TEST_F(BufferValidationTest, CreationParameterReflectionForOOMBuffer) {
|
||||
constexpr uint64_t kAmazinglyLargeSize = 0x1234'5678'90AB'CDEF;
|
||||
wgpu::BufferDescriptor desc;
|
||||
desc.usage = wgpu::BufferUsage::Storage;
|
||||
desc.size = kAmazinglyLargeSize;
|
||||
|
||||
// OOM!
|
||||
wgpu::Buffer buf;
|
||||
ASSERT_DEVICE_ERROR(buf = device.CreateBuffer(&desc));
|
||||
|
||||
// Reflection data is still exactly what was in the descriptor.
|
||||
EXPECT_EQ(wgpu::BufferUsage::Storage, buf.GetUsage());
|
||||
EXPECT_EQ(kAmazinglyLargeSize, buf.GetSize());
|
||||
}
|
||||
|
||||
// Test that buffer reflection doesn't show internal usages
|
||||
TEST_F(BufferValidationTest, CreationParameterReflectionNoInternalUsage) {
|
||||
wgpu::BufferDescriptor desc;
|
||||
desc.size = 16;
|
||||
// QueryResolve also adds kInternalStorageBuffer for processing of queries.
|
||||
desc.usage = wgpu::BufferUsage::QueryResolve;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&desc);
|
||||
|
||||
// The reflection shouldn't show kInternalStorageBuffer
|
||||
EXPECT_EQ(wgpu::BufferUsage::QueryResolve, buf.GetUsage());
|
||||
EXPECT_EQ(16u, buf.GetSize());
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
|||
wireClient->GetMemoryTransferService()->CreateReadHandle(descriptor->size));
|
||||
if (readHandle == nullptr) {
|
||||
device->InjectError(WGPUErrorType_OutOfMemory, "Failed to create buffer mapping");
|
||||
return device->CreateErrorBuffer();
|
||||
return CreateError(device, descriptor);
|
||||
}
|
||||
cmd.readHandleCreateInfoLength = readHandle->SerializeCreateSize();
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
|||
wireClient->GetMemoryTransferService()->CreateWriteHandle(descriptor->size));
|
||||
if (writeHandle == nullptr) {
|
||||
device->InjectError(WGPUErrorType_OutOfMemory, "Failed to create buffer mapping");
|
||||
return device->CreateErrorBuffer();
|
||||
return CreateError(device, descriptor);
|
||||
}
|
||||
cmd.writeHandleCreateInfoLength = writeHandle->SerializeCreateSize();
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
|||
buffer->mDevice = device;
|
||||
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
||||
buffer->mSize = descriptor->size;
|
||||
buffer->mUsage = static_cast<WGPUBufferUsage>(descriptor->usage);
|
||||
buffer->mDestructWriteHandleOnUnmap = false;
|
||||
|
||||
if (descriptor->mappedAtCreation) {
|
||||
|
@ -124,10 +125,12 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
|||
}
|
||||
|
||||
// static
|
||||
WGPUBuffer Buffer::CreateError(Device* device) {
|
||||
WGPUBuffer Buffer::CreateError(Device* device, const WGPUBufferDescriptor* descriptor) {
|
||||
auto* allocation = device->client->BufferAllocator().New(device->client);
|
||||
allocation->object->mDevice = device;
|
||||
allocation->object->mDeviceIsAlive = device->GetAliveWeakPtr();
|
||||
allocation->object->mSize = descriptor->size;
|
||||
allocation->object->mUsage = static_cast<WGPUBufferUsage>(descriptor->usage);
|
||||
|
||||
DeviceCreateErrorBufferCmd cmd;
|
||||
cmd.self = ToAPI(device);
|
||||
|
@ -365,6 +368,14 @@ void Buffer::Destroy() {
|
|||
client->SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
WGPUBufferUsage Buffer::GetUsage() const {
|
||||
return mUsage;
|
||||
}
|
||||
|
||||
uint64_t Buffer::GetSize() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
bool Buffer::IsMappedForReading() const {
|
||||
return mMapState == MapState::MappedForRead;
|
||||
}
|
||||
|
|
|
@ -28,10 +28,8 @@ class Device;
|
|||
|
||||
class Buffer final : public ObjectBase {
|
||||
public:
|
||||
using ObjectBase::ObjectBase;
|
||||
|
||||
static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor);
|
||||
static WGPUBuffer CreateError(Device* device);
|
||||
static WGPUBuffer CreateError(Device* device, const WGPUBufferDescriptor* descriptor);
|
||||
|
||||
Buffer(Client* client, uint32_t refcount, uint32_t id);
|
||||
~Buffer();
|
||||
|
@ -51,6 +49,10 @@ class Buffer final : public ObjectBase {
|
|||
|
||||
void Destroy();
|
||||
|
||||
// Note that these values can be arbitrary since they aren't validated in the wire client.
|
||||
WGPUBufferUsage GetUsage() const;
|
||||
uint64_t GetSize() const;
|
||||
|
||||
private:
|
||||
void CancelCallbacksForDisconnect() override;
|
||||
void ClearAllCallbacks(WGPUBufferMapAsyncStatus status);
|
||||
|
@ -90,6 +92,7 @@ class Buffer final : public ObjectBase {
|
|||
};
|
||||
RequestTracker<MapRequestData> mRequests;
|
||||
uint64_t mSize = 0;
|
||||
WGPUBufferUsage mUsage;
|
||||
|
||||
// Only one mapped pointer can be active at a time because Unmap clears all the in-flight
|
||||
// requests.
|
||||
|
|
|
@ -200,7 +200,8 @@ WGPUBuffer Device::CreateBuffer(const WGPUBufferDescriptor* descriptor) {
|
|||
}
|
||||
|
||||
WGPUBuffer Device::CreateErrorBuffer() {
|
||||
return Buffer::CreateError(this);
|
||||
WGPUBufferDescriptor fakeDescriptor = {};
|
||||
return Buffer::CreateError(this, &fakeDescriptor);
|
||||
}
|
||||
|
||||
WGPUQueue Device::GetQueue() {
|
||||
|
|
Loading…
Reference in New Issue