1 /*---------------------------------------------------------------------------*
2 
3   Copyright 2010-2014 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 tesselation
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