1 // Copyright 2019 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef DAWNWIRE_CLIENT_BUFFER_H_ 16 #define DAWNWIRE_CLIENT_BUFFER_H_ 17 18 #include <dawn/webgpu.h> 19 20 #include "dawn_wire/WireClient.h" 21 #include "dawn_wire/client/ObjectBase.h" 22 #include "dawn_wire/client/RequestTracker.h" 23 24 namespace dawn_wire { namespace client { 25 26 class Device; 27 28 class Buffer final : public ObjectBase { 29 public: 30 using ObjectBase::ObjectBase; 31 32 static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor); 33 static WGPUBuffer CreateError(Device* device); 34 35 ~Buffer(); 36 37 bool OnMapAsyncCallback(uint64_t requestSerial, 38 uint32_t status, 39 uint64_t readDataUpdateInfoLength, 40 const uint8_t* readDataUpdateInfo); 41 void MapAsync(WGPUMapModeFlags mode, 42 size_t offset, 43 size_t size, 44 WGPUBufferMapCallback callback, 45 void* userdata); 46 void* GetMappedRange(size_t offset, size_t size); 47 const void* GetConstMappedRange(size_t offset, size_t size); 48 void Unmap(); 49 50 void Destroy(); 51 52 private: 53 void CancelCallbacksForDisconnect() override; 54 void ClearAllCallbacks(WGPUBufferMapAsyncStatus status); 55 56 bool IsMappedForReading() const; 57 bool IsMappedForWriting() const; 58 bool CheckGetMappedRangeOffsetSize(size_t offset, size_t size) const; 59 60 void FreeMappedData(); 61 62 Device* mDevice; 63 64 enum class MapRequestType { None, Read, Write }; 65 66 enum class MapState { 67 Unmapped, 68 MappedForRead, 69 MappedForWrite, 70 MappedAtCreation, 71 }; 72 73 // We want to defer all the validation to the server, which means we could have multiple 74 // map request in flight at a single time and need to track them separately. 75 // On well-behaved applications, only one request should exist at a single time. 76 struct MapRequestData { 77 WGPUBufferMapCallback callback = nullptr; 78 void* userdata = nullptr; 79 size_t offset = 0; 80 size_t size = 0; 81 82 // When the buffer is destroyed or unmapped too early, the unmappedBeforeX status takes 83 // precedence over the success value returned from the server. However Error statuses 84 // from the server take precedence over the client-side status. 85 WGPUBufferMapAsyncStatus clientStatus = WGPUBufferMapAsyncStatus_Success; 86 87 MapRequestType type = MapRequestType::None; 88 }; 89 RequestTracker<MapRequestData> mRequests; 90 uint64_t mSize = 0; 91 92 // Only one mapped pointer can be active at a time because Unmap clears all the in-flight 93 // requests. 94 // TODO(enga): Use a tagged pointer to save space. 95 std::unique_ptr<MemoryTransferService::ReadHandle> mReadHandle = nullptr; 96 std::unique_ptr<MemoryTransferService::WriteHandle> mWriteHandle = nullptr; 97 MapState mMapState = MapState::Unmapped; 98 bool mDestructWriteHandleOnUnmap = false; 99 100 void* mMappedData = nullptr; 101 size_t mMapOffset = 0; 102 size_t mMapSize = 0; 103 104 std::weak_ptr<bool> mDeviceIsAlive; 105 }; 106 107 }} // namespace dawn_wire::client 108 109 #endif // DAWNWIRE_CLIENT_BUFFER_H_ 110