1 /*---------------------------------------------------------------------------*
2
3 Copyright (C) Nintendo. All rights reserved.
4
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10
11 *---------------------------------------------------------------------------*/
12
13 #ifndef _GX2UTINLINE_H_
14 #define _GX2UTINLINE_H_
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 /// @addtogroup GX2UTGX2RGroup
21 /// @{
22
23 /// \brief Simple wrapper on a display list buffer that stores the used byte count
24 typedef struct _GX2UTManagedDisplayList
25 {
26 GX2RBuffer displayList;
27 u32 sizeUsed;
28 } GX2UTManagedDisplayList;
29
30
31 /// \brief Convert a GX2IndexFormat to a size in bytes
32 ///
33 /// \donotcall \threadsafe \devonly \enddonotcall
34 ///
GX2UTGetIndexSize(GX2IndexFormat format)35 GX2_INLINE u32 GX2UTGetIndexSize(GX2IndexFormat format)
36 {
37 ASSERT(format==GX2_INDEX_FORMAT_U16 || format==GX2_INDEX_FORMAT_U32 || format==GX2_INDEX_FORMAT_U16_LE || format==GX2_INDEX_FORMAT_U32_LE);
38 return (format==GX2_INDEX_FORMAT_U32 || format==GX2_INDEX_FORMAT_U32_LE) ? 4 : 2;
39 }
40
41
42 /// \brief Convert a size in bytes to a GX2IndexFormat
43 /// \note Won't work with the _LE formats
44 ///
45 /// \donotcall \threadsafe \devonly \enddonotcall
46 ///
GX2UTGetIndexFormat(u32 size)47 GX2_INLINE GX2IndexFormat GX2UTGetIndexFormat(u32 size)
48 {
49 ASSERT(size==2 || size==4);
50 return (size==4) ? GX2_INDEX_FORMAT_U32 : GX2_INDEX_FORMAT_U16;
51 }
52
53 /// \brief Get the size in bytes of a buffer
54 /// \note The actual allocated size may be slightly larger due to end alignment
55 ///
56 /// \donotcall \threadsafe \devonly \enddonotcall
57 ///
GX2UTGetBufferSize(const GX2RBuffer * gx2Buffer)58 GX2_INLINE u32 GX2UTGetBufferSize(const GX2RBuffer* gx2Buffer)
59 {
60 return gx2Buffer->elementSize * gx2Buffer->elementCount;
61 }
62
63
64 /// \brief Zero out the given buffer struct
65 /// \note GX2Buffers should be initialized to 0 before use, in particular the reserved fields must be zero.
66 ///
67 /// \donotcall \threadsafe \devonly \enddonotcall
68 ///
GX2UTZeroBufferStruct(GX2RBuffer * gx2Buffer)69 GX2_INLINE void GX2UTZeroBufferStruct(GX2RBuffer* gx2Buffer)
70 {
71 memset(gx2Buffer, 0, sizeof(GX2RBuffer));
72 }
73
74 /// \brief Fill in a GX2Buffer struct
75 /// \note This function will also ensure the reserved fields are zero.
76 /// NOTE: no creation is done!
77 ///
78 /// \donotcall \threadsafe \devonly \enddonotcall
79 ///
GX2UTInitBufferStruct(GX2RBuffer * gx2Buffer,GX2RResourceFlags resourceFlags,u32 elementSize,u32 elementCount)80 GX2_INLINE void GX2UTInitBufferStruct(GX2RBuffer* gx2Buffer, GX2RResourceFlags resourceFlags, u32 elementSize, u32 elementCount)
81 {
82 gx2Buffer->resourceFlags = resourceFlags;
83 gx2Buffer->elementSize = elementSize;
84 gx2Buffer->elementCount = elementCount;
85
86 gx2Buffer->reserved[0]=0;
87 }
88
89
90 /// \brief Fill in a GX2Buffer struct and create the buffer.
91 /// \note This function will also ensure the reserved fields are zero.
92 ///
93 /// \donotcall \gx2_typical \userheap \enddonotcall
94 ///
GX2UTCreateBuffer(GX2RBuffer * gx2Buffer,GX2RResourceFlags resourceFlags,u32 elementSize,u32 elementCount)95 GX2_INLINE GX2Boolean GX2UTCreateBuffer(GX2RBuffer* gx2Buffer, GX2RResourceFlags resourceFlags, u32 elementSize, u32 elementCount)
96 {
97 gx2Buffer->resourceFlags = resourceFlags;
98 gx2Buffer->elementSize = elementSize;
99 gx2Buffer->elementCount = elementCount;
100 gx2Buffer->reserved[0]=0;
101
102 return GX2RCreateBuffer(gx2Buffer);
103 }
104
105
106 /// \brief Create a typical vertex buffer
107 ///
108 /// \donotcall \gx2_typical \userheap \enddonotcall
109 ///
GX2UTCreateVertexBuffer(GX2RBuffer * gx2Buffer,u32 elementSize,u32 elementCount)110 GX2_INLINE GX2Boolean GX2UTCreateVertexBuffer(GX2RBuffer* gx2Buffer, u32 elementSize, u32 elementCount)
111 {
112 return GX2UTCreateBuffer(gx2Buffer, (GX2RResourceFlags)(GX2R_BIND_VERTEX_BUFFER | GX2R_USAGE_CPU_READWRITE | GX2R_USAGE_GPU_READ), elementSize, elementCount);
113 }
114
115 /// \brief Create a typical index buffer
116 ///
117 /// \donotcall \gx2_typical \userheap \enddonotcall
118 ///
GX2UTCreateIndexBuffer(GX2RBuffer * gx2Buffer,u32 elementSize,u32 elementCount)119 GX2_INLINE GX2Boolean GX2UTCreateIndexBuffer(GX2RBuffer* gx2Buffer, u32 elementSize, u32 elementCount)
120 {
121 ASSERT(elementSize==2 || elementSize==4);
122 return GX2UTCreateBuffer(gx2Buffer, (GX2RResourceFlags)(GX2R_BIND_INDEX_BUFFER | GX2R_USAGE_CPU_READWRITE | GX2R_USAGE_GPU_READ), elementSize, elementCount);
123 }
124
125
126 /// \brief Create a typical uniform block buffer
127 ///
128 /// \donotcall \gx2_typical \userheap \enddonotcall
129 ///
GX2UTCreateUniformBlock(GX2RBuffer * gx2Buffer,u32 elementSize,u32 elementCount)130 GX2_INLINE GX2Boolean GX2UTCreateUniformBlock(GX2RBuffer* gx2Buffer, u32 elementSize, u32 elementCount)
131 {
132 return GX2UTCreateBuffer(gx2Buffer, (GX2RResourceFlags)(GX2R_BIND_UNIFORM_BLOCK | GX2R_USAGE_CPU_READWRITE | GX2R_USAGE_GPU_READ), elementSize, elementCount);
133 }
134
135
136 /// \brief Create a typical shader buffer
137 ///
138 /// \donotcall \gx2_typical \userheap \enddonotcall
139 ///
GX2UTCreateShaderProgram(GX2RBuffer * gx2Buffer,u32 programSize)140 GX2_INLINE GX2Boolean GX2UTCreateShaderProgram(GX2RBuffer* gx2Buffer, u32 programSize)
141 {
142 return GX2UTCreateBuffer(gx2Buffer, (GX2RResourceFlags)(GX2R_BIND_SHADER_PROGRAM | GX2R_USAGE_CPU_READWRITE | GX2R_USAGE_GPU_READ), programSize, 1);
143 }
144
145
146 /// \brief Create a typical display list buffer
147 ///
148 /// \donotcall \gx2_typical \userheap \enddonotcall
149 ///
GX2UTCreateDisplayList(GX2RBuffer * gx2Buffer,u32 byteSize)150 GX2_INLINE GX2Boolean GX2UTCreateDisplayList(GX2RBuffer* gx2Buffer, u32 byteSize)
151 {
152 return GX2UTCreateBuffer(gx2Buffer, (GX2RResourceFlags)(GX2R_BIND_DISPLAY_LIST | GX2R_USAGE_CPU_READWRITE | GX2R_USAGE_GPU_READ), byteSize, 1);
153 }
154
155
156 /// \brief Create a "managed" display list that stores its current used size
157 ///
158 /// \donotcall \gx2_typical \userheap \enddonotcall
159 ///
GX2UTCreateManagedDisplayList(GX2UTManagedDisplayList * managedDisplayList,u32 byteSize)160 GX2_INLINE GX2Boolean GX2UTCreateManagedDisplayList(GX2UTManagedDisplayList* managedDisplayList, u32 byteSize)
161 {
162 managedDisplayList->sizeUsed = 0;
163 return GX2UTCreateDisplayList(&managedDisplayList->displayList, byteSize);
164 }
165
166 /// \brief Begin a managed display list
167 ///
168 /// \donotcall \gx2_dl \enddonotcall
169 ///
GX2UTBeginManagedDisplayList(GX2UTManagedDisplayList * managedDisplayList)170 GX2_INLINE void GX2UTBeginManagedDisplayList(GX2UTManagedDisplayList* managedDisplayList)
171 {
172 managedDisplayList->sizeUsed = 0;
173 GX2RBeginDisplayList(&managedDisplayList->displayList);
174 }
175
176 /// \brief End a managed display list
177 ///
178 /// \donotcall \gx2_typical \enddonotcall
179 ///
GX2UTEndManagedDisplayList(GX2UTManagedDisplayList * managedDisplayList)180 GX2_INLINE void GX2UTEndManagedDisplayList(GX2UTManagedDisplayList* managedDisplayList)
181 {
182 ASSERT(managedDisplayList->sizeUsed==0); // either not created or mismatched begin/end
183 managedDisplayList->sizeUsed = GX2REndDisplayList(&managedDisplayList->displayList);
184 }
185
186 /// \brief Call a managed display list
187 ///
188 /// \donotcall \gx2_typical \enddonotcall
189 ///
190 /// \writesgpu
191 /// \alwayswritesgpu
192 ///
GX2UTCallManagedDisplayList(const GX2UTManagedDisplayList * managedDisplayList)193 GX2_INLINE void GX2UTCallManagedDisplayList(const GX2UTManagedDisplayList* managedDisplayList)
194 {
195 GX2RCallDisplayList(&managedDisplayList->displayList, managedDisplayList->sizeUsed);
196 }
197
198 /// \brief Direct call a managed display list
199 ///
200 /// \donotcall \nomulticore \gx2_dl \enddonotcall
201 ///
202 /// \writesgpu
203 /// \alwayswritesgpu
204 ///
GX2UTDirectCallManagedDisplayList(const GX2UTManagedDisplayList * managedDisplayList)205 GX2_INLINE void GX2UTDirectCallManagedDisplayList(const GX2UTManagedDisplayList* managedDisplayList)
206 {
207 GX2RDirectCallDisplayList(&managedDisplayList->displayList, managedDisplayList->sizeUsed);
208 }
209
210
211 /// \brief Set an attribute buffer deriving the stride automatically from the buffer elementSize
212 ///
213 /// \donotcall \gx2_typical \enddonotcall
214 ///
215 /// \writesgpu
216 /// \alwayswritesgpu
217 ///
GX2UTSetAttributeBuffer(const GX2RBuffer * vertexBuffer,u32 slot,u32 byteOffset)218 GX2_INLINE void GX2UTSetAttributeBuffer(const GX2RBuffer* vertexBuffer, u32 slot, u32 byteOffset)
219 {
220 GX2RSetAttributeBuffer(vertexBuffer, slot, vertexBuffer->elementSize, byteOffset);
221 }
222
223 /// \brief Draw deriving the index format and index count automatically, with no offsets or instancing
224 ///
225 /// \donotcall \gx2_typical \enddonotcall
226 ///
227 /// \writesgpu
228 /// \alwayswritesgpu
229 ///
GX2UTDrawIndexed(GX2PrimitiveType primitiveType,const GX2RBuffer * indexBuffer)230 GX2_INLINE void GX2UTDrawIndexed(GX2PrimitiveType primitiveType, const GX2RBuffer* indexBuffer)
231 {
232 GX2RDrawIndexed(primitiveType, indexBuffer, GX2UTGetIndexFormat(indexBuffer->elementSize), indexBuffer->elementCount, 0, 0, 1);
233 }
234
235 /// \brief Draw immediate deriving the index format and index count automatically, with no offsets or instancing
236 ///
237 /// \donotcall \gx2_typical \enddonotcall
238 ///
239 /// \writesgpu
240 /// \alwayswritesgpu
241 ///
GX2UTDrawIndexedImmediate(GX2PrimitiveType primitiveType,const GX2RBuffer * indexBuffer)242 GX2_INLINE void GX2UTDrawIndexedImmediate(GX2PrimitiveType primitiveType, const GX2RBuffer* indexBuffer)
243 {
244 GX2RDrawIndexedImmediate(primitiveType, indexBuffer, GX2UTGetIndexFormat(indexBuffer->elementSize), indexBuffer->elementCount, 0, 0, 1);
245 }
246
247 /// \brief Create a geometry shader input ring buffer of the correct size for the given vertex shader
248 ///
249 /// \donotcall \gx2_typical \userheap \enddonotcall
250 ///
GX2UTCreateGeometryShaderInputRingBuffer(GX2RBuffer * gx2Buffer,const GX2VertexShader * pVertexShader)251 GX2_INLINE GX2Boolean GX2UTCreateGeometryShaderInputRingBuffer(GX2RBuffer* gx2Buffer, const GX2VertexShader *pVertexShader)
252 {
253 u32 byteCount= GX2CalcGeometryShaderInputRingBufferSize(pVertexShader->ringItemsize);
254 return GX2UTCreateBuffer(gx2Buffer, (GX2RResourceFlags)(GX2R_BIND_GS_RING | GX2R_USAGE_GPU_READ | GX2R_USAGE_GPU_WRITE), byteCount, 1);
255 }
256
257 /// \brief Create a geometry shader output ring buffer of the correct size for the given geometry shader
258 ///
259 /// \donotcall \gx2_typical \userheap \enddonotcall
260 ///
GX2UTCreateGeometryShaderOutputRingBuffer(GX2RBuffer * gx2Buffer,const GX2GeometryShader * pGeometryShader)261 GX2_INLINE GX2Boolean GX2UTCreateGeometryShaderOutputRingBuffer(GX2RBuffer* gx2Buffer, const GX2GeometryShader *pGeometryShader)
262 {
263 u32 byteCount= GX2CalcGeometryShaderOutputRingBufferSize(pGeometryShader->ringItemsize);
264 return GX2UTCreateBuffer(gx2Buffer, (GX2RResourceFlags)(GX2R_BIND_GS_RING | GX2R_USAGE_GPU_READ | GX2R_USAGE_GPU_WRITE), byteCount, 1);
265 }
266
267 /// \brief Set the geometry shader input and output buffers
268 ///
269 /// \donotcall \gx2_typical \enddonotcall
270 ///
271 /// \writesgpu
272 /// \alwayswritesgpu
273 ///
GX2UTSetGeometryShaderRingBuffers(const GX2RBuffer * ringInBuffer,const GX2RBuffer * ringOutBuffer)274 GX2_INLINE void GX2UTSetGeometryShaderRingBuffers(const GX2RBuffer* ringInBuffer, const GX2RBuffer* ringOutBuffer)
275 {
276 GX2RSetGeometryShaderInputRingBuffer(ringInBuffer);
277 GX2RSetGeometryShaderOutputRingBuffer(ringOutBuffer);
278 }
279
280 /// \brief Initialize the fetch shader assuming no tessellation
281 ///
282 /// \donotcall \threadsafe \devonly \enddonotcall
283 ///
GX2UTInitFetchShader(GX2FetchShader * fetchShader,GX2RBuffer * shaderProgram,u32 attribCount,const GX2AttribStream * attribStreams)284 GX2_INLINE void GX2UTInitFetchShader(GX2FetchShader* fetchShader, GX2RBuffer* shaderProgram, u32 attribCount, const GX2AttribStream* attribStreams)
285 {
286 GX2RInitFetchShader(fetchShader, shaderProgram, attribCount, attribStreams, GX2_FETCH_SHADER_TESSELATION_NONE, GX2_TESSELLATION_MODE_DISCRETE);
287 }
288
289
290 /// \brief Lock the buffer, copy byteCount bytes from pSrc into it, and unlock
291 ///
292 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
293 ///
GX2UTFillBufferEx(GX2RBuffer * gx2Buffer,void * pSrc,u32 byteCount)294 GX2_INLINE void GX2UTFillBufferEx(GX2RBuffer* gx2Buffer, void *pSrc, u32 byteCount)
295 {
296 void *pMem=GX2RLockBuffer(gx2Buffer);
297 memcpy(pMem, pSrc, byteCount);
298 GX2RUnlockBuffer(gx2Buffer);
299 }
300
301 /// \brief Lock the buffer, copy bytes from pSrc into it (size of entire buffer), and unlock.
302 ///
303 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
304 ///
GX2UTFillBuffer(GX2RBuffer * gx2Buffer,void * pSrc)305 GX2_INLINE void GX2UTFillBuffer(GX2RBuffer* gx2Buffer, void *pSrc)
306 {
307 GX2UTFillBufferEx(gx2Buffer, pSrc, GX2UTGetBufferSize(gx2Buffer));
308 }
309
310 /// \brief Call \ref GX2RInvalidateBuffer() with GX2R_OPTION_NONE
311 ///
312 /// \donotcall \gx2_typical \enddonotcall
313 ///
314 /// \writesgpu
315 /// \writesgpu{if the buffer may be read or written by GPU.}
316 ///
GX2UTInvalidateBuffer(const GX2RBuffer * gx2Buffer)317 GX2_INLINE void GX2UTInvalidateBuffer(const GX2RBuffer* gx2Buffer)
318 {
319 GX2RInvalidateBuffer(gx2Buffer, GX2R_OPTION_NONE);
320 }
321
322 /// \brief Macro to name a buffer by its variable name
323 #define GX2UTSetBufferVarName(x) GX2RSetBufferName(&x, #x)
324
325
326 /// \brief Lock/Unlock the buffer and endian swap the contents
327 ///
328 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
329 ///
GX2UTEndianSwapBuffer(GX2RBuffer * gx2Buffer)330 GX2_INLINE void GX2UTEndianSwapBuffer(GX2RBuffer* gx2Buffer)
331 {
332 void *pMem=GX2RLockBuffer(gx2Buffer);
333 GX2EndianSwap(pMem, GX2UTGetBufferSize(gx2Buffer));
334 GX2RUnlockBuffer(gx2Buffer);
335 }
336
337 /// \brief Lock/Unlock the buffer and endian swap the contents, pass options to \ref GX2RUnlockBufferEx
338 ///
339 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
340 ///
GX2UTEndianSwapBufferEx(GX2RBuffer * gx2Buffer,GX2RResourceFlags optionFlags)341 GX2_INLINE void GX2UTEndianSwapBufferEx(GX2RBuffer* gx2Buffer, GX2RResourceFlags optionFlags)
342 {
343 void *pMem=GX2RLockBuffer(gx2Buffer);
344 GX2EndianSwap(pMem, GX2UTGetBufferSize(gx2Buffer));
345 GX2RUnlockBufferEx(gx2Buffer, optionFlags);
346 }
347
348
349 /// \brief Set up all the user fields of a GX2Surface.
350 /// \note This function does not call \ref GX2CalcSurfaceSizeAndAlignment
351 ///
352 /// \donotcall \threadsafe \devonly \enddonotcall
353 ///
GX2UTInitSurfaceStruct(GX2Surface * gx2Surface,GX2RResourceFlags resourceFlags,u32 width,u32 height,u32 depth,u32 numMips,GX2SurfaceDim dim,GX2SurfaceFormat format,GX2AAMode aa)354 GX2_INLINE void GX2UTInitSurfaceStruct(GX2Surface *gx2Surface, GX2RResourceFlags resourceFlags, u32 width, u32 height, u32 depth,
355 u32 numMips, GX2SurfaceDim dim, GX2SurfaceFormat format, GX2AAMode aa)
356 {
357 GX2_CHECK_ENUM_RANGE(dim, GX2_SURFACE_DIM)
358 GX2_CHECK_ENUM_RANGE(format, GX2_SURFACE_FORMAT)
359 GX2_CHECK_ENUM_RANGE(aa, GX2_AA_MODE)
360
361 gx2Surface->dim = dim;
362 gx2Surface->width = width;
363 gx2Surface->height = height;
364 gx2Surface->depth = depth;
365 gx2Surface->numMips = numMips;
366 gx2Surface->format = format;
367 gx2Surface->aa = aa;
368 gx2Surface->resourceFlags = resourceFlags;
369 gx2Surface->tileMode = GX2_TILE_MODE_DEFAULT;
370 gx2Surface->swizzle = 0;
371
372 gx2Surface->imagePtr = NULL;
373 gx2Surface->mipPtr = NULL;
374 }
375
376 /// \brief Set the color buffers and depth buffer for rendering.
377 ///
378 /// This function sets the color buffers and depth buffers for rendering. It
379 /// is valid to pass 0 as the number of color buffers for depth only rendering.
380 /// It is valid to pass NULL as the depth buffer.
381 ///
382 /// \note The AA mode will be set to the value found in the first GX2ColorBuffer
383 /// or, if there are no color buffers, the value in the GX2DepthBuffer.
384 ///
385 /// \note Functions \ref GX2SetColorBuffer() and \ref GX2SetDepthBuffer() can be
386 /// used to individually set color buffers and the depth buffer.
387 ///
388 /// \param numColorBuffers Number of color buffers, starting at GX2_RENDER_TARGET_0.
389 /// \param colorBuffers Pointer to an array of GX2ColorBuffer pointers.
390 /// \param depthBuffer Pointer to a GX2DepthBuffer, may be NULL.
391 ///
392 /// \donotcall \gx2_typical \enddonotcall
393 ///
394 /// \writesgpu
395 /// \alwayswritesgpu
396 ///
GX2UTSetRenderTargets(u32 numColorBuffers,const GX2ColorBuffer ** colorBuffers,const GX2DepthBuffer * depthBuffer)397 GX2_INLINE void GX2UTSetRenderTargets(u32 numColorBuffers,
398 const GX2ColorBuffer **colorBuffers,
399 const GX2DepthBuffer *depthBuffer)
400 {
401 if(numColorBuffers != 0)
402 {
403 u32 i;
404 ASSERT(numColorBuffers <= (u32)GX2_RENDER_TARGET_LAST + 1);
405 ASSERT(colorBuffers);
406
407 for(i = 0; i < numColorBuffers; i++)
408 {
409 ASSERT(colorBuffers[i]);
410 GX2SetColorBuffer(colorBuffers[i], (GX2RenderTarget)i);
411 }
412 }
413
414 if(depthBuffer != NULL)
415 {
416 GX2SetDepthBuffer(depthBuffer);
417 if(numColorBuffers == 0)
418 {
419 GX2SetAAMode(depthBuffer->surface.aa);
420 }
421 }
422 }
423
424 /// @}
425 /// @addtogroup GX2UTCaptureGroup
426 /// @{
427
428 /// \brief Thin wrapper on GX2DebugTagUserString(GX2_DEBUG_TAG_INDENT)
429 ///
430 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
431 ///
GX2UTDebugTagIndent(const char * formatString,...)432 GX2_INLINE void GX2UTDebugTagIndent( const char* formatString, ... )
433 {
434 va_list args;
435 va_start(args, formatString);
436 GX2DebugTagUserStringVA(GX2_DEBUG_TAG_INDENT, formatString, args);
437 va_end(args);
438 }
439
440 /// \brief Thin wrapper on GX2DebugTagUserString(GX2_DEBUG_TAG_UNDENT)
441 ///
442 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
443 ///
GX2UTDebugTagUndent(void)444 GX2_INLINE void GX2UTDebugTagUndent(void)
445 {
446 GX2DebugTagUserString(GX2_DEBUG_TAG_UNDENT, NULL);
447 }
448
449 /// \brief Thin wrapper on GX2DebugTagUserString(GX2_DEBUG_TAG_COMMENT)
450 ///
451 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
452 ///
GX2UTDebugTagComment(const char * formatString,...)453 GX2_INLINE void GX2UTDebugTagComment( const char* formatString, ... )
454 {
455 va_list args;
456 va_start(args, formatString);
457 GX2DebugTagUserStringVA(GX2_DEBUG_TAG_COMMENT, formatString, args);
458 va_end(args);
459 }
460
461 /// \brief Thin wrapper on GX2DebugTagUserString(GX2_DEBUG_TAG_BOOKMARK)
462 ///
463 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
464 ///
GX2UTDebugTagBookmark(const char * formatString,...)465 GX2_INLINE void GX2UTDebugTagBookmark( const char* formatString, ... )
466 {
467 va_list args;
468 va_start(args, formatString);
469 GX2DebugTagUserStringVA(GX2_DEBUG_TAG_BOOKMARK, formatString, args);
470 va_end(args);
471 }
472
473 /// \brief Convenience function for rounding a u32 to the nearest power of 2.
474 ///
475 /// \donotcall \threadsafe \devonly \enddonotcall
476 ///
GX2UTRoundNearestPow2(u32 value)477 GX2_INLINE u32 GX2UTRoundNearestPow2(u32 value)
478 {
479 // Special bit-twiddle that rounds up to nearest power of 2.
480 value--;
481 value |= value >> 1;
482 value |= value >> 2;
483 value |= value >> 4;
484 value |= value >> 8;
485 value |= value >> 16;
486 value++;
487
488 return value;
489 }
490
491
492 /// @}
493
494 #ifdef __cplusplus
495 }
496 #endif // __cplusplus
497
498 #endif // _GX2UTINLINE_H_
499