1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
/*
* Copyright 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// This file contains the common parts of command buffer formats.
#ifndef GPU_COMMAND_BUFFER_COMMON_CROSS_CMD_BUFFER_COMMON_H_
#define GPU_COMMAND_BUFFER_COMMON_CROSS_CMD_BUFFER_COMMON_H_
#include "base/basictypes.h"
#include "gpu/command_buffer/common/types.h"
#include "gpu/command_buffer/common/bitfield_helpers.h"
#include "gpu/command_buffer/common/logging.h"
namespace command_buffer {
namespace cmd {
enum ArgFlags {
kFixed = 0x0,
kAtLeastN = 0x1,
};
} // namespace cmd
// 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 ComputeNumEntries(size_t size_in_bytes) {
return static_cast<uint32>(
(size_in_bytes + sizeof(uint32) - 1) / sizeof(uint32)); // 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); // NOLINT
}
// Struct that defines the command header in the command buffer.
struct CommandHeader {
Uint32 size:8;
Uint32 command:24;
void Init(uint32 _command, uint32 _size) {
DCHECK_LT(_size, 256u);
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() {
COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_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 size_of_data_in_bytes) {
COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_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 size_in_bytes) {
COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
DCHECK_GE(size_in_bytes, sizeof(T)); // NOLINT
Init(T::kCmdId, ComputeNumEntries(size_in_bytes));
}
};
COMPILE_ASSERT(sizeof(CommandHeader) == 4, Sizeof_CommandHeader_is_not_4);
// Union that defines possible command buffer entries.
union CommandBufferEntry {
CommandHeader value_header;
Uint32 value_uint32;
Int32 value_int32;
float value_float;
};
COMPILE_ASSERT(sizeof(CommandBufferEntry) == 4,
Sizeof_CommandBufferEntry_is_not_4);
// Make sure the compiler does not add extra padding to any of the command
// structures.
#pragma pack(push, 1)
// 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) {
COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_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) {
COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_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 size_of_data_in_bytes) {
COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_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 total_size_in_bytes) {
COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
DCHECK_GE(total_size_in_bytes, sizeof(T)); // NOLINT
return reinterpret_cast<char*>(cmd) +
RoundSizeToMultipleOfEntries(total_size_in_bytes);
}
struct SharedMemory {
void Init(uint32 _id, uint32 _offset) {
id = _id;
offset = _offset;
}
uint32 id;
uint32 offset;
};
COMPILE_ASSERT(offsetof(SharedMemory, id) == 0,
Offsetof_SharedMemory_id_not_0);
COMPILE_ASSERT(offsetof(SharedMemory, offset) == 4,
Offsetof_SharedMemory_offset_not_4);
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 */ \
// 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 = 1023, // reserve 1024 spaces for common commands.
};
COMPILE_ASSERT(kNumCommands - 1 <= kLastCommonId, Too_many_common_commands);
const char* GetCommandName(CommandId id);
struct Noop {
typedef Noop ValueType;
static const CommandId kCmdId = kNoop;
static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
void SetHeader(uint32 skip_count) {
header.Init(kCmdId, skip_count + 1);
}
void Init(uint32 skip_count) {
SetHeader(skip_count);
}
static void* Set(void* cmd, uint32 skip_count) {
static_cast<ValueType*>(cmd)->Init(skip_count);
return NextImmediateCmdAddress<ValueType>(
cmd, skip_count * sizeof(CommandBufferEntry)); // NOLINT
}
CommandHeader header;
};
COMPILE_ASSERT(sizeof(Noop) == 4, Sizeof_Noop_is_not_4);
COMPILE_ASSERT(offsetof(Noop, header) == 0, Offsetof_Noop_header_not_0);
struct SetToken {
typedef SetToken ValueType;
static const CommandId kCmdId = kSetToken;
static const cmd::ArgFlags kArgFlags = cmd::kFixed;
void SetHeader() {
header.SetCmd<ValueType>();
}
void Init(uint32 _token) {
SetHeader();
token = _token;
}
static void* Set(void* cmd, uint32 token) {
static_cast<ValueType*>(cmd)->Init(token);
return NextCmdAddress<ValueType>(cmd);
}
CommandHeader header;
uint32 token;
};
COMPILE_ASSERT(sizeof(SetToken) == 8, Sizeof_SetToken_is_not_8);
COMPILE_ASSERT(offsetof(SetToken, header) == 0,
Offsetof_SetToken_header_not_0);
COMPILE_ASSERT(offsetof(SetToken, token) == 4,
Offsetof_SetToken_token_not_4);
} // namespace cmd
#pragma pack(pop)
} // namespace command_buffer
#endif // GPU_COMMAND_BUFFER_COMMON_CROSS_CMD_BUFFER_COMMON_H_
|