blob: 343aa7feaba90a041abc88fe2a2b1db219e98fc9 [file] [log] [blame]
// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_DAWN_NATIVE_BUFFER_H_
#define SRC_DAWN_NATIVE_BUFFER_H_
#include <memory>
#include "dawn/common/NonCopyable.h"
#include "dawn/native/Error.h"
#include "dawn/native/Forward.h"
#include "dawn/native/IntegerTypes.h"
#include "dawn/native/ObjectBase.h"
#include "dawn/native/dawn_platform.h"
namespace dawn::native {
struct CopyTextureToBufferCmd;
enum class MapType : uint32_t;
MaybeError ValidateBufferDescriptor(DeviceBase* device, const BufferDescriptor* descriptor);
static constexpr wgpu::BufferUsage kReadOnlyBufferUsages =
wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::Index |
wgpu::BufferUsage::Vertex | wgpu::BufferUsage::Uniform | kReadOnlyStorageBuffer |
wgpu::BufferUsage::Indirect;
static constexpr wgpu::BufferUsage kMappableBufferUsages =
wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite;
class BufferBase : public ApiObjectBase {
public:
enum class BufferState {
Unmapped,
PendingMap,
Mapped,
MappedAtCreation,
Destroyed,
};
static BufferBase* MakeError(DeviceBase* device, const BufferDescriptor* descriptor);
ObjectType GetType() const override;
uint64_t GetSize() const;
uint64_t GetAllocatedSize() const;
// |GetUsageExternalOnly| returns the usage with which the buffer was created using the
// base WebGPU API. Additional usages may be added for internal state tracking. |GetUsage|
// returns the union of base usage and the usages added internally.
wgpu::BufferUsage GetUsage() const;
wgpu::BufferUsage GetUsageExternalOnly() const;
MaybeError MapAtCreation();
void OnMapRequestCompleted(MapRequestID mapID, WGPUBufferMapAsyncStatus status);
MaybeError ValidateCanUseOnQueueNow() const;
bool IsFullBufferRange(uint64_t offset, uint64_t size) const;
bool NeedsInitialization() const;
bool IsDataInitialized() const;
void SetIsDataInitialized();
void MarkUsedInPendingCommands();
virtual void* GetMappedPointer() = 0;
void* GetMappedRange(size_t offset, size_t size, bool writable = true);
MaybeError Unmap();
// Dawn API
void APIMapAsync(wgpu::MapMode mode,
size_t offset,
size_t size,
WGPUBufferMapCallback callback,
void* userdata);
void* APIGetMappedRange(size_t offset, size_t size);
const void* APIGetConstMappedRange(size_t offset, size_t size);
void APIUnmap();
void APIDestroy();
wgpu::BufferUsage APIGetUsage() const;
wgpu::BufferMapState APIGetMapState() const;
uint64_t APIGetSize() const;
protected:
BufferBase(DeviceBase* device, const BufferDescriptor* descriptor);
BufferBase(DeviceBase* device, const BufferDescriptor* descriptor, ObjectBase::ErrorTag tag);
void DestroyImpl() override;
~BufferBase() override;
MaybeError MapAtCreationInternal();
uint64_t mAllocatedSize = 0;
ExecutionSerial mLastUsageSerial = ExecutionSerial(0);
private:
// A helper structure to enforce that the mapAsync callback is called only at the very end of
// methods that might trigger callbacks. Non-copyable but movable for the assertion in the
// destructor to ensure not to forget to call the callback
struct [[nodiscard]] PendingMappingCallback : public NonCopyable {
WGPUBufferMapCallback callback;
void* userdata;
WGPUBufferMapAsyncStatus status;
PendingMappingCallback();
~PendingMappingCallback();
PendingMappingCallback(PendingMappingCallback&& other);
PendingMappingCallback& operator=(PendingMappingCallback&& other);
void Call();
};
PendingMappingCallback WillCallMappingCallback(MapRequestID mapID,
WGPUBufferMapAsyncStatus status);
virtual MaybeError MapAtCreationImpl() = 0;
virtual MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) = 0;
virtual void UnmapImpl() = 0;
virtual bool IsCPUWritableAtCreation() const = 0;
MaybeError CopyFromStagingBuffer();
MaybeError ValidateMapAsync(wgpu::MapMode mode,
size_t offset,
size_t size,
WGPUBufferMapAsyncStatus* status) const;
MaybeError ValidateUnmap() const;
bool CanGetMappedRange(bool writable, size_t offset, size_t size) const;
PendingMappingCallback UnmapInternal(WGPUBufferMapAsyncStatus callbackStatus);
uint64_t mSize = 0;
wgpu::BufferUsage mUsage = wgpu::BufferUsage::None;
BufferState mState;
bool mIsDataInitialized = false;
// mStagingBuffer is used to implement mappedAtCreation for
// buffers with non-mappable usage. It is transiently allocated
// and released when the mappedAtCreation-buffer is unmapped.
// Because `mStagingBuffer` itself is directly mappable, it will
// not create another staging buffer.
// i.e. buffer->mStagingBuffer->mStagingBuffer... is not possible.
Ref<BufferBase> mStagingBuffer;
WGPUBufferMapCallback mMapCallback = nullptr;
void* mMapUserdata = nullptr;
MapRequestID mLastMapID = MapRequestID(0);
wgpu::MapMode mMapMode = wgpu::MapMode::None;
size_t mMapOffset = 0;
size_t mMapSize = 0;
};
} // namespace dawn::native
#endif // SRC_DAWN_NATIVE_BUFFER_H_