1 // Copyright 2020 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_CHUNKEDCOMMANDSERIALIZER_H_ 16 #define DAWNWIRE_CHUNKEDCOMMANDSERIALIZER_H_ 17 18 #include "common/Alloc.h" 19 #include "common/Compiler.h" 20 #include "dawn_wire/Wire.h" 21 #include "dawn_wire/WireCmd_autogen.h" 22 23 #include <algorithm> 24 #include <cstring> 25 #include <memory> 26 27 namespace dawn_wire { 28 29 class ChunkedCommandSerializer { 30 public: 31 ChunkedCommandSerializer(CommandSerializer* serializer); 32 33 template <typename Cmd> SerializeCommand(const Cmd & cmd)34 void SerializeCommand(const Cmd& cmd) { 35 SerializeCommand(cmd, 0, [](SerializeBuffer*) { return WireResult::Success; }); 36 } 37 38 template <typename Cmd, typename ExtraSizeSerializeFn> SerializeCommand(const Cmd & cmd,size_t extraSize,ExtraSizeSerializeFn && SerializeExtraSize)39 void SerializeCommand(const Cmd& cmd, 40 size_t extraSize, 41 ExtraSizeSerializeFn&& SerializeExtraSize) { 42 SerializeCommandImpl( 43 cmd, 44 [](const Cmd& cmd, size_t requiredSize, SerializeBuffer* serializeBuffer) { 45 return cmd.Serialize(requiredSize, serializeBuffer); 46 }, 47 extraSize, std::forward<ExtraSizeSerializeFn>(SerializeExtraSize)); 48 } 49 50 template <typename Cmd> SerializeCommand(const Cmd & cmd,const ObjectIdProvider & objectIdProvider)51 void SerializeCommand(const Cmd& cmd, const ObjectIdProvider& objectIdProvider) { 52 SerializeCommand(cmd, objectIdProvider, 0, 53 [](SerializeBuffer*) { return WireResult::Success; }); 54 } 55 56 template <typename Cmd, typename ExtraSizeSerializeFn> SerializeCommand(const Cmd & cmd,const ObjectIdProvider & objectIdProvider,size_t extraSize,ExtraSizeSerializeFn && SerializeExtraSize)57 void SerializeCommand(const Cmd& cmd, 58 const ObjectIdProvider& objectIdProvider, 59 size_t extraSize, 60 ExtraSizeSerializeFn&& SerializeExtraSize) { 61 SerializeCommandImpl( 62 cmd, 63 [&objectIdProvider](const Cmd& cmd, size_t requiredSize, 64 SerializeBuffer* serializeBuffer) { 65 return cmd.Serialize(requiredSize, serializeBuffer, objectIdProvider); 66 }, 67 extraSize, std::forward<ExtraSizeSerializeFn>(SerializeExtraSize)); 68 } 69 70 private: 71 template <typename Cmd, typename SerializeCmdFn, typename ExtraSizeSerializeFn> SerializeCommandImpl(const Cmd & cmd,SerializeCmdFn && SerializeCmd,size_t extraSize,ExtraSizeSerializeFn && SerializeExtraSize)72 void SerializeCommandImpl(const Cmd& cmd, 73 SerializeCmdFn&& SerializeCmd, 74 size_t extraSize, 75 ExtraSizeSerializeFn&& SerializeExtraSize) { 76 size_t commandSize = cmd.GetRequiredSize(); 77 size_t requiredSize = commandSize + extraSize; 78 79 if (requiredSize <= mMaxAllocationSize) { 80 char* allocatedBuffer = static_cast<char*>(mSerializer->GetCmdSpace(requiredSize)); 81 if (allocatedBuffer != nullptr) { 82 SerializeBuffer serializeBuffer(allocatedBuffer, requiredSize); 83 WireResult r1 = SerializeCmd(cmd, requiredSize, &serializeBuffer); 84 WireResult r2 = SerializeExtraSize(&serializeBuffer); 85 if (DAWN_UNLIKELY(r1 != WireResult::Success || r2 != WireResult::Success)) { 86 mSerializer->OnSerializeError(); 87 } 88 } 89 return; 90 } 91 92 auto cmdSpace = std::unique_ptr<char[]>(AllocNoThrow<char>(requiredSize)); 93 if (!cmdSpace) { 94 return; 95 } 96 SerializeBuffer serializeBuffer(cmdSpace.get(), requiredSize); 97 WireResult r1 = SerializeCmd(cmd, requiredSize, &serializeBuffer); 98 WireResult r2 = SerializeExtraSize(&serializeBuffer); 99 if (DAWN_UNLIKELY(r1 != WireResult::Success || r2 != WireResult::Success)) { 100 mSerializer->OnSerializeError(); 101 return; 102 } 103 SerializeChunkedCommand(cmdSpace.get(), requiredSize); 104 } 105 106 void SerializeChunkedCommand(const char* allocatedBuffer, size_t remainingSize); 107 108 CommandSerializer* mSerializer; 109 size_t mMaxAllocationSize; 110 }; 111 112 } // namespace dawn_wire 113 114 #endif // DAWNWIRE_CHUNKEDCOMMANDSERIALIZER_H_ 115