| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file contains the common parts of command buffer formats. |
| |
| #ifndef GPU_COMMAND_BUFFER_COMMON_CMD_BUFFER_COMMON_H_ |
| #define GPU_COMMAND_BUFFER_COMMON_CMD_BUFFER_COMMON_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include "base/check_op.h" |
| #include "gpu/gpu_export.h" |
| |
| namespace gpu { |
| |
| namespace cmd { |
| enum ArgFlags { |
| kFixed = 0x0, |
| kAtLeastN = 0x1 |
| }; |
| } // namespace cmd |
| |
| // Pack & unpack Command cmd_flags |
| #define CMD_FLAG_SET_TRACE_LEVEL(level) (level & 3) |
| #define CMD_FLAG_GET_TRACE_LEVEL(cmd_flags) (cmd_flags & 3) |
| |
| // Computes the number of command buffer entries needed for a certain size. In |
| // other words it rounds up to a multiple of entries. |
| inline uint32_t ComputeNumEntries(size_t size_in_bytes) { |
| return static_cast<uint32_t>( |
| (size_in_bytes + sizeof(uint32_t) - 1) / sizeof(uint32_t)); // NOLINT |
| } |
| |
| // Rounds up to a multiple of entries in bytes. |
| inline size_t RoundSizeToMultipleOfEntries(size_t size_in_bytes) { |
| return ComputeNumEntries(size_in_bytes) * sizeof(uint32_t); // NOLINT |
| } |
| |
| // Struct that defines the command header in the command buffer. |
| struct CommandHeader { |
| uint32_t size:21; |
| uint32_t command:11; |
| |
| GPU_EXPORT static const int32_t kMaxSize = (1 << 21) - 1; |
| |
| void Init(uint32_t _command, int32_t _size) { |
| DCHECK_LE(_size, kMaxSize); |
| command = _command; |
| size = _size; |
| } |
| |
| // Sets the header based on the passed in command. Can not be used for |
| // variable sized commands like immediate commands or Noop. |
| template <typename T> |
| void SetCmd() { |
| static_assert(T::kArgFlags == cmd::kFixed, |
| "T::kArgFlags should equal cmd::kFixed"); |
| Init(T::kCmdId, ComputeNumEntries(sizeof(T))); // NOLINT |
| } |
| |
| // Sets the header by a size in bytes of the immediate data after the command. |
| template <typename T> |
| void SetCmdBySize(uint32_t size_of_data_in_bytes) { |
| static_assert(T::kArgFlags == cmd::kAtLeastN, |
| "T::kArgFlags should equal cmd::kAtLeastN"); |
| Init(T::kCmdId, |
| ComputeNumEntries(sizeof(T) + size_of_data_in_bytes)); // NOLINT |
| } |
| |
| // Sets the header by a size in bytes. |
| template <typename T> |
| void SetCmdByTotalSize(uint32_t size_in_bytes) { |
| static_assert(T::kArgFlags == cmd::kAtLeastN, |
| "T::kArgFlags should equal cmd::kAtLeastN"); |
| DCHECK_GE(size_in_bytes, sizeof(T)); // NOLINT |
| Init(T::kCmdId, ComputeNumEntries(size_in_bytes)); |
| } |
| |
| static CommandHeader FromVolatile(const volatile CommandHeader& other) { |
| // const_cast is safe because the copy constructor is trivial. |
| return const_cast<const CommandHeader&>(other); |
| } |
| }; |
| |
| static_assert(sizeof(CommandHeader) == 4, |
| "size of CommandHeader should equal 4"); |
| |
| // Union that defines possible command buffer entries. |
| union CommandBufferEntry { |
| CommandHeader value_header; |
| uint32_t value_uint32; |
| int32_t value_int32; |
| float value_float; |
| }; |
| |
| #define GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT 4 |
| const size_t kCommandBufferEntrySize = GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT; |
| |
| static_assert(sizeof(CommandBufferEntry) == kCommandBufferEntrySize, |
| "size of CommandBufferEntry should equal " |
| "kCommandBufferEntrySize"); |
| |
| // Command buffer is GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT byte aligned. |
| #pragma pack(push, 4) |
| static_assert(GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT == 4, |
| "pragma pack alignment must be equal to " |
| "GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT"); |
| |
| // Gets the address of memory just after a structure in a typesafe way. This is |
| // used for IMMEDIATE commands to get the address of the place to put the data. |
| // Immediate command put their data direclty in the command buffer. |
| // Parameters: |
| // cmd: Address of command. |
| template <typename T> |
| void* ImmediateDataAddress(T* cmd) { |
| static_assert(T::kArgFlags == cmd::kAtLeastN, |
| "T::kArgFlags should equal cmd::kAtLeastN"); |
| return reinterpret_cast<char*>(cmd) + sizeof(*cmd); |
| } |
| |
| // Gets the address of the place to put the next command in a typesafe way. |
| // This can only be used for fixed sized commands. |
| template <typename T> |
| // Parameters: |
| // cmd: Address of command. |
| void* NextCmdAddress(void* cmd) { |
| static_assert(T::kArgFlags == cmd::kFixed, |
| "T::kArgFlags should equal cmd::kFixed"); |
| return reinterpret_cast<char*>(cmd) + sizeof(T); |
| } |
| |
| // Gets the address of the place to put the next command in a typesafe way. |
| // This can only be used for variable sized command like IMMEDIATE commands. |
| // Parameters: |
| // cmd: Address of command. |
| // size_of_data_in_bytes: Size of the data for the command. |
| template <typename T> |
| void* NextImmediateCmdAddress(void* cmd, uint32_t size_of_data_in_bytes) { |
| static_assert(T::kArgFlags == cmd::kAtLeastN, |
| "T::kArgFlags should equal cmd::kAtLeastN"); |
| return reinterpret_cast<char*>(cmd) + sizeof(T) + // NOLINT |
| RoundSizeToMultipleOfEntries(size_of_data_in_bytes); |
| } |
| |
| // Gets the address of the place to put the next command in a typesafe way. |
| // This can only be used for variable sized command like IMMEDIATE commands. |
| // Parameters: |
| // cmd: Address of command. |
| // size_of_cmd_in_bytes: Size of the cmd and data. |
| template <typename T> |
| void* NextImmediateCmdAddressTotalSize(void* cmd, |
| uint32_t total_size_in_bytes) { |
| static_assert(T::kArgFlags == cmd::kAtLeastN, |
| "T::kArgFlags should equal cmd::kAtLeastN"); |
| DCHECK_GE(total_size_in_bytes, sizeof(T)); // NOLINT |
| return reinterpret_cast<char*>(cmd) + |
| RoundSizeToMultipleOfEntries(total_size_in_bytes); |
| } |
| |
| namespace cmd { |
| |
| // This macro is used to safely and convienently expand the list of commnad |
| // buffer commands in to various lists and never have them get out of sync. To |
| // add a new command, add it this list, create the corresponding structure below |
| // and then add a function in gapi_decoder.cc called Handle_COMMAND_NAME where |
| // COMMAND_NAME is the name of your command structure. |
| // |
| // NOTE: THE ORDER OF THESE MUST NOT CHANGE (their id is derived by order) |
| #define COMMON_COMMAND_BUFFER_CMDS(OP) \ |
| OP(Noop) /* 0 */ \ |
| OP(SetToken) /* 1 */ \ |
| OP(SetBucketSize) /* 2 */ \ |
| OP(SetBucketData) /* 3 */ \ |
| OP(SetBucketDataImmediate) /* 4 */ \ |
| OP(GetBucketStart) /* 5 */ \ |
| OP(GetBucketData) /* 6 */ \ |
| OP(InsertFenceSync) /* 7 */ |
| |
| // Common commands. |
| enum CommandId { |
| #define COMMON_COMMAND_BUFFER_CMD_OP(name) k ## name, |
| |
| COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) |
| |
| #undef COMMON_COMMAND_BUFFER_CMD_OP |
| |
| kNumCommands, |
| kLastCommonId = 255 // reserve 256 spaces for common commands. |
| }; |
| |
| static_assert(kNumCommands - 1 <= kLastCommonId, "too many commands"); |
| |
| const char* GetCommandName(CommandId id); |
| |
| // A Noop command. |
| struct Noop { |
| typedef Noop ValueType; |
| static const CommandId kCmdId = kNoop; |
| static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); |
| |
| void SetHeader(uint32_t skip_count) { |
| DCHECK_GT(skip_count, 0u); |
| header.Init(kCmdId, skip_count); |
| } |
| |
| void Init(uint32_t skip_count) { |
| SetHeader(skip_count); |
| } |
| |
| static void* Set(void* cmd, uint32_t skip_count) { |
| static_cast<ValueType*>(cmd)->Init(skip_count); |
| return NextImmediateCmdAddress<ValueType>( |
| cmd, skip_count * sizeof(CommandBufferEntry)); // NOLINT |
| } |
| |
| CommandHeader header; |
| }; |
| |
| static_assert(sizeof(Noop) == 4, "size of Noop should equal 4"); |
| static_assert(offsetof(Noop, header) == 0, |
| "offset of Noop.header should equal 0"); |
| |
| // The SetToken command puts a token in the command stream that you can |
| // use to check if that token has been passed in the command stream. |
| struct SetToken { |
| typedef SetToken ValueType; |
| static const CommandId kCmdId = kSetToken; |
| static const cmd::ArgFlags kArgFlags = cmd::kFixed; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); |
| |
| void SetHeader() { |
| header.SetCmd<ValueType>(); |
| } |
| |
| void Init(uint32_t _token) { |
| SetHeader(); |
| token = _token; |
| } |
| static void* Set(void* cmd, uint32_t token) { |
| static_cast<ValueType*>(cmd)->Init(token); |
| return NextCmdAddress<ValueType>(cmd); |
| } |
| |
| CommandHeader header; |
| uint32_t token; |
| }; |
| |
| static_assert(sizeof(SetToken) == 8, "size of SetToken should equal 8"); |
| static_assert(offsetof(SetToken, header) == 0, |
| "offset of SetToken.header should equal 0"); |
| static_assert(offsetof(SetToken, token) == 4, |
| "offset of SetToken.token should equal 4"); |
| |
| // Sets the size of a bucket for collecting data on the service side. |
| // This is a utility for gathering data on the service side so it can be used |
| // all at once when some service side API is called. It removes the need to add |
| // special commands just to support a particular API. For example, any API |
| // command that needs a string needs a way to send that string to the API over |
| // the command buffers. While you can require that the command buffer or |
| // transfer buffer be large enough to hold the largest string you can send, |
| // using this command removes that restriction by letting you send smaller |
| // pieces over and build up the data on the service side. |
| // |
| // You can clear a bucket on the service side and thereby free memory by sending |
| // a size of 0. |
| struct SetBucketSize { |
| typedef SetBucketSize ValueType; |
| static const CommandId kCmdId = kSetBucketSize; |
| static const cmd::ArgFlags kArgFlags = cmd::kFixed; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); |
| |
| void SetHeader() { |
| header.SetCmd<ValueType>(); |
| } |
| |
| void Init(uint32_t _bucket_id, uint32_t _size) { |
| SetHeader(); |
| bucket_id = _bucket_id; |
| size = _size; |
| } |
| static void* Set(void* cmd, uint32_t _bucket_id, uint32_t _size) { |
| static_cast<ValueType*>(cmd)->Init(_bucket_id, _size); |
| return NextCmdAddress<ValueType>(cmd); |
| } |
| |
| CommandHeader header; |
| uint32_t bucket_id; |
| uint32_t size; |
| }; |
| |
| static_assert(sizeof(SetBucketSize) == 12, |
| "size of SetBucketSize should equal 12"); |
| static_assert(offsetof(SetBucketSize, header) == 0, |
| "offset of SetBucketSize.header should equal 0"); |
| static_assert(offsetof(SetBucketSize, bucket_id) == 4, |
| "offset of SetBucketSize.bucket_id should equal 4"); |
| static_assert(offsetof(SetBucketSize, size) == 8, |
| "offset of SetBucketSize.size should equal 8"); |
| |
| // Sets the contents of a portion of a bucket on the service side from data in |
| // shared memory. |
| // See SetBucketSize. |
| struct SetBucketData { |
| typedef SetBucketData ValueType; |
| static const CommandId kCmdId = kSetBucketData; |
| static const cmd::ArgFlags kArgFlags = cmd::kFixed; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); |
| |
| void SetHeader() { |
| header.SetCmd<ValueType>(); |
| } |
| |
| void Init(uint32_t _bucket_id, |
| uint32_t _offset, |
| uint32_t _size, |
| uint32_t _shared_memory_id, |
| uint32_t _shared_memory_offset) { |
| SetHeader(); |
| bucket_id = _bucket_id; |
| offset = _offset; |
| size = _size; |
| shared_memory_id = _shared_memory_id; |
| shared_memory_offset = _shared_memory_offset; |
| } |
| static void* Set(void* cmd, |
| uint32_t _bucket_id, |
| uint32_t _offset, |
| uint32_t _size, |
| uint32_t _shared_memory_id, |
| uint32_t _shared_memory_offset) { |
| static_cast<ValueType*>(cmd)->Init( |
| _bucket_id, |
| _offset, |
| _size, |
| _shared_memory_id, |
| _shared_memory_offset); |
| return NextCmdAddress<ValueType>(cmd); |
| } |
| |
| CommandHeader header; |
| uint32_t bucket_id; |
| uint32_t offset; |
| uint32_t size; |
| uint32_t shared_memory_id; |
| uint32_t shared_memory_offset; |
| }; |
| |
| static_assert(sizeof(SetBucketData) == 24, |
| "size of SetBucketData should be 24"); |
| static_assert(offsetof(SetBucketData, header) == 0, |
| "offset of SetBucketData.header should be 0"); |
| static_assert(offsetof(SetBucketData, bucket_id) == 4, |
| "offset of SetBucketData.bucket_id should be 4"); |
| static_assert(offsetof(SetBucketData, offset) == 8, |
| "offset of SetBucketData.offset should be 8"); |
| static_assert(offsetof(SetBucketData, size) == 12, |
| "offset of SetBucketData.size should be 12"); |
| static_assert(offsetof(SetBucketData, shared_memory_id) == 16, |
| "offset of SetBucketData.shared_memory_id should be 16"); |
| static_assert(offsetof(SetBucketData, shared_memory_offset) == 20, |
| "offset of SetBucketData.shared_memory_offset should be 20"); |
| |
| // Sets the contents of a portion of a bucket on the service side from data in |
| // the command buffer. |
| // See SetBucketSize. |
| struct SetBucketDataImmediate { |
| typedef SetBucketDataImmediate ValueType; |
| static const CommandId kCmdId = kSetBucketDataImmediate; |
| static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); |
| |
| void SetHeader(uint32_t _size) { header.SetCmdBySize<ValueType>(_size); } |
| |
| void Init(uint32_t _bucket_id, |
| uint32_t _offset, |
| uint32_t _size) { |
| SetHeader(_size); |
| bucket_id = _bucket_id; |
| offset = _offset; |
| size = _size; |
| } |
| static void* Set(void* cmd, |
| uint32_t _bucket_id, |
| uint32_t _offset, |
| uint32_t _size) { |
| static_cast<ValueType*>(cmd)->Init( |
| _bucket_id, |
| _offset, |
| _size); |
| return NextImmediateCmdAddress<ValueType>(cmd, _size); |
| } |
| |
| CommandHeader header; |
| uint32_t bucket_id; |
| uint32_t offset; |
| uint32_t size; |
| }; |
| |
| static_assert(sizeof(SetBucketDataImmediate) == 16, |
| "size of SetBucketDataImmediate should be 16"); |
| static_assert(offsetof(SetBucketDataImmediate, header) == 0, |
| "offset of SetBucketDataImmediate.header should be 0"); |
| static_assert(offsetof(SetBucketDataImmediate, bucket_id) == 4, |
| "offset of SetBucketDataImmediate.bucket_id should be 4"); |
| static_assert(offsetof(SetBucketDataImmediate, offset) == 8, |
| "offset of SetBucketDataImmediate.offset should be 8"); |
| static_assert(offsetof(SetBucketDataImmediate, size) == 12, |
| "offset of SetBucketDataImmediate.size should be 12"); |
| |
| // Gets the start of a bucket the service has available. Sending a variable size |
| // result back to the client and the portion of that result that fits in the |
| // supplied shared memory. If the size of the result is larger than the supplied |
| // shared memory the rest of the bucket's contents can be retrieved with |
| // GetBucketData. |
| // |
| // This is used for example for any API that returns a string. The problem is |
| // the largest thing you can send back in 1 command is the size of your shared |
| // memory. This command along with GetBucketData implements a way to get a |
| // result a piece at a time to help solve that problem in a generic way. |
| struct GetBucketStart { |
| typedef GetBucketStart ValueType; |
| static const CommandId kCmdId = kGetBucketStart; |
| static const cmd::ArgFlags kArgFlags = cmd::kFixed; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); |
| |
| typedef uint32_t Result; |
| |
| void SetHeader() { |
| header.SetCmd<ValueType>(); |
| } |
| |
| void Init(uint32_t _bucket_id, |
| uint32_t _result_memory_id, |
| uint32_t _result_memory_offset, |
| uint32_t _data_memory_size, |
| uint32_t _data_memory_id, |
| uint32_t _data_memory_offset) { |
| SetHeader(); |
| bucket_id = _bucket_id; |
| result_memory_id = _result_memory_id; |
| result_memory_offset = _result_memory_offset; |
| data_memory_size = _data_memory_size; |
| data_memory_id = _data_memory_id; |
| data_memory_offset = _data_memory_offset; |
| } |
| static void* Set(void* cmd, |
| uint32_t _bucket_id, |
| uint32_t _result_memory_id, |
| uint32_t _result_memory_offset, |
| uint32_t _data_memory_size, |
| uint32_t _data_memory_id, |
| uint32_t _data_memory_offset) { |
| static_cast<ValueType*>(cmd)->Init( |
| _bucket_id, |
| _result_memory_id, |
| _result_memory_offset, |
| _data_memory_size, |
| _data_memory_id, |
| _data_memory_offset); |
| return NextCmdAddress<ValueType>(cmd); |
| } |
| |
| CommandHeader header; |
| uint32_t bucket_id; |
| uint32_t result_memory_id; |
| uint32_t result_memory_offset; |
| uint32_t data_memory_size; |
| uint32_t data_memory_id; |
| uint32_t data_memory_offset; |
| }; |
| |
| static_assert(sizeof(GetBucketStart) == 28, |
| "size of GetBucketStart should be 28"); |
| static_assert(offsetof(GetBucketStart, header) == 0, |
| "offset of GetBucketStart.header should be 0"); |
| static_assert(offsetof(GetBucketStart, bucket_id) == 4, |
| "offset of GetBucketStart.bucket_id should be 4"); |
| static_assert(offsetof(GetBucketStart, result_memory_id) == 8, |
| "offset of GetBucketStart.result_memory_id should be 8"); |
| static_assert(offsetof(GetBucketStart, result_memory_offset) == 12, |
| "offset of GetBucketStart.result_memory_offset should be 12"); |
| static_assert(offsetof(GetBucketStart, data_memory_size) == 16, |
| "offset of GetBucketStart.data_memory_size should be 16"); |
| static_assert(offsetof(GetBucketStart, data_memory_id) == 20, |
| "offset of GetBucketStart.data_memory_id should be 20"); |
| static_assert(offsetof(GetBucketStart, data_memory_offset) == 24, |
| "offset of GetBucketStart.data_memory_offset should be 24"); |
| |
| // Gets a piece of a result the service as available. |
| // See GetBucketSize. |
| struct GetBucketData { |
| typedef GetBucketData ValueType; |
| static const CommandId kCmdId = kGetBucketData; |
| static const cmd::ArgFlags kArgFlags = cmd::kFixed; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); |
| |
| void SetHeader() { |
| header.SetCmd<ValueType>(); |
| } |
| |
| void Init(uint32_t _bucket_id, |
| uint32_t _offset, |
| uint32_t _size, |
| uint32_t _shared_memory_id, |
| uint32_t _shared_memory_offset) { |
| SetHeader(); |
| bucket_id = _bucket_id; |
| offset = _offset; |
| size = _size; |
| shared_memory_id = _shared_memory_id; |
| shared_memory_offset = _shared_memory_offset; |
| } |
| static void* Set(void* cmd, |
| uint32_t _bucket_id, |
| uint32_t _offset, |
| uint32_t _size, |
| uint32_t _shared_memory_id, |
| uint32_t _shared_memory_offset) { |
| static_cast<ValueType*>(cmd)->Init( |
| _bucket_id, |
| _offset, |
| _size, |
| _shared_memory_id, |
| _shared_memory_offset); |
| return NextCmdAddress<ValueType>(cmd); |
| } |
| |
| CommandHeader header; |
| uint32_t bucket_id; |
| uint32_t offset; |
| uint32_t size; |
| uint32_t shared_memory_id; |
| uint32_t shared_memory_offset; |
| }; |
| |
| static_assert(sizeof(GetBucketData) == 24, |
| "size of GetBucketData should be 24"); |
| static_assert(offsetof(GetBucketData, header) == 0, |
| "offset of GetBucketData.header should be 0"); |
| static_assert(offsetof(GetBucketData, bucket_id) == 4, |
| "offset of GetBucketData.bucket_id should be 4"); |
| static_assert(offsetof(GetBucketData, offset) == 8, |
| "offset of GetBucketData.offset should be 8"); |
| static_assert(offsetof(GetBucketData, size) == 12, |
| "offset of GetBucketData.size should be 12"); |
| static_assert(offsetof(GetBucketData, shared_memory_id) == 16, |
| "offset of GetBucketData.shared_memory_id should be 16"); |
| static_assert(offsetof(GetBucketData, shared_memory_offset) == 20, |
| "offset of GetBucketData.shared_memory_offset should be 20"); |
| |
| struct InsertFenceSync { |
| typedef InsertFenceSync ValueType; |
| static const CommandId kCmdId = kInsertFenceSync; |
| static const cmd::ArgFlags kArgFlags = cmd::kFixed; |
| static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); |
| |
| void SetHeader() { header.SetCmd<ValueType>(); } |
| |
| void Init(uint64_t _release_count) { |
| SetHeader(); |
| release_count_0 = static_cast<uint32_t>(_release_count & 0xFFFFFFFF); |
| release_count_1 = |
| static_cast<uint32_t>((_release_count >> 32) & 0xFFFFFFFF); |
| } |
| |
| void* Set(void* cmd, uint64_t _release_count) { |
| static_cast<ValueType*>(cmd)->Init(_release_count); |
| return NextCmdAddress<ValueType>(cmd); |
| } |
| |
| uint64_t release_count() const volatile { |
| return (static_cast<uint64_t>(release_count_1) << 32) + |
| static_cast<uint64_t>(release_count_0); |
| } |
| |
| gpu::CommandHeader header; |
| uint32_t release_count_0; |
| uint32_t release_count_1; |
| }; |
| |
| static_assert(sizeof(InsertFenceSync) == 12, |
| "size of InsertFenceSync should be 12"); |
| static_assert(offsetof(InsertFenceSync, header) == 0, |
| "offset of InsertFenceSync header should be 0"); |
| static_assert(offsetof(InsertFenceSync, release_count_0) == 4, |
| "offset of InsertFenceSync release_count_0 should be 4"); |
| static_assert(offsetof(InsertFenceSync, release_count_1) == 8, |
| "offset of InsertFenceSync release_count_1 should be 8"); |
| |
| } // namespace cmd |
| |
| #pragma pack(pop) |
| |
| } // namespace gpu |
| |
| #endif // GPU_COMMAND_BUFFER_COMMON_CMD_BUFFER_COMMON_H_ |