/*---------------------------------------------------------------------------* Copyright (C) 2010-2011 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ // gx2Manage.h // // Declares management function prototypes for gx2 library. #ifndef _CAFE_GX2_MANAGE_H_ #define _CAFE_GX2_MANAGE_H_ #ifdef __cplusplus extern "C" { #endif // __cplusplus /// @addtogroup GX2ManagementGroup /// @{ /// @addtogroup GX2ManagementInitGroup /// @{ /// \brief Initialize GX2. /// /// GX2Init should be called only once until GX2Shutdown is called (no ref-counting is done). /// /// Calling GX2Init determines which CPU core becomes the "main" core. Only the thread running on /// the main core can submit GX2 commands to the GPU. One thread each on other core can still /// create GX2 display lists. Threads that call GX2 commands must have their affinity set to only a /// single core! One reason for these restrictions is that GX2 makes use of the write-gather /// facility of the CPU, which has only 1 instance for each core. /// /// The command-buffer pool base address should be set with the \ref GX2_INIT_ATTRIB_CB_BASE attribute. /// The size of the command buffer pool should be specified with the \ref GX2_INIT_ATTRIB_CB_SIZE attribute. /// If \ref GX2_INIT_ATTRIB_CB_BASE is not set, GX2 will allocate the buffer from the default heap. /// /// GX2Init will get argc/argv from the OS, although you may override those values by specifying the /// GX2_INIT_ATTRIB_ARGC and GX2_INIT_ATTRIB_ARGV attributes. /// /// Command-line arguments for GX2 are gathered from the OS. The arguments that GX2 recognizes are: /// - -tvesync : Waits for TV handshake to finish before continuing /// - -profile_mode=N : Sets the \ref GX2ProfileMode to the value N (in decimal, or 0xN for hex) /// - -toss_stage=N : Sets the \ref GX2TossStage to the value N /// /// The profiling mode can also be set with \ref GX2_INIT_ATTRIB_PROFILE_MODE attrib. /// The toss stage can also be set with \ref GX2_INIT_ATTRIB_TOSS_STAGE attrib. /// Command-line values for these will override attribute values. /// /// \param initAttribs A list of \ref GX2InitAttrib, each followed by their value, /// terminated with 0 (\ref GX2_INIT_ATTRIB_NULL), or NULL if no attribs needed. /// /// \donotcall /// \gx2_dl /// \nomulticore /// \userheap{\ref GX2_INIT_ATTRIB_CB_BASE is not set. This will be from the default heap.} /// \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2Init(u32 *initAttribs); /// \brief Shutdown GX2. /// /// \note If you didn't call \ref GX2Init from the default core, then you must be sure /// to synchronize the cores after calling GX2Shutdown to prevent a race condition where /// the OS shuts down lower-level drivers before GX2 is properly shut down. /// /// \note GX2 frees command buffer pool from system dedicated heap, if it is allocated. /// /// \donotcall /// \gx2_dl /// \nomulticore /// \userheap{\ref GX2_INIT_ATTRIB_CB_BASE is not set when \ref GX2Init is called. This will be to the default heap.} /// \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2Shutdown(void); /// \brief Returns core id which GX2 was initialized on; returns -1 if GX2 is not initialized. /// /// \donotcall \threadsafe \devonly \enddonotcall /// s32 GX2API GX2GetMainCoreId(void); /// @} /// @addtogroup GX2ManagementSyncGroup /// @{ /// \brief Send any buffered graphics commands to the GPU. /// /// \donotcall \nomulticore \gx2_dl \enddonotcall /// /// \writesgpu /// \writesgpu{if commands are in the command buffer} /// void GX2API GX2Flush(void); /// \brief Have CPU wait until GPU finishes all submitted commands. /// /// \note This puts the thread to sleep until the work is done. /// \note This calls GX2Flush internally so that you don't have to. /// \note This must be called immediately prior to calling /// ProcUIProcessMessage. /// /// \donotcall \nomulticore \gx2_dl \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// GX2Boolean GX2API GX2DrawDone(void); /// \brief Get timestamp of last submitted (flushed) command buffer. /// /// \donotcall \threadsafe \devonly \enddonotcall /// u64 GX2API GX2GetLastSubmittedTimeStamp(void); /// \brief Get timestamp of last command buffer that GPU has finished processing. /// /// \donotcall \notthreadsafe \devonly \enddonotcall /// u64 GX2API GX2GetRetiredTimeStamp(void); /// \brief Wait until the timestamp is returned from the GPU. GX2_FALSE will be returned if the /// timeout was reached before the timestamp value was returned from the GPU. /// /// \donotcall \gx2_typical \enddonotcall /// /// \writesgpu /// \directwritesgpu /// GX2Boolean GX2API GX2WaitTimeStamp(u64 ts); // ---- /// \brief GX2 display list overrun callback structure. /// /// When GX2 detects a display overrun condition, it will invoke the optional /// \ref GX2_CB_EVENT_DL_OVERRUN callback function. The user-provided data /// pointer \p userDataPtr must point to a structure that begins with a /// \ref GX2DisplayListOverrun structure when invoking \ref GX2SetEventCallback. /// The \ref GX2DisplayListOverrun structure provides for communication between /// GX2 and the user in handling the overrun condition. /// /// When the user callback function is invoked, GX2 will initialize the /// contents of \p oldDisplayList and \p oldByteSize with the display list /// information for the buffer that caused the overrun in the current core. /// \p newByteSize will be set to the minimum required space needed. The /// callback function must allocate a new display list buffer and set /// \p newDisplayList and \p newByteSize appropriately before returning /// control to GX2. /// /// \warning Display lists generated using the overrun callback must be /// called sequentially. /// /// \sa GX2SetEventCallback /// typedef struct _GX2DisplayListOverrun { void *oldDisplayList; ///< Pointer to the original display list buffer u32 oldByteSize; ///< Final size of the original display list buffer void *newDisplayList; ///< Pointer to a new display list buffer u32 newByteSize; ///< Size of the new display list buffer that was /// allocated. When the callback is called, GX2 /// sets this to the minimum size that should be /// allocated for the new display list. u32 padding0; ///< Reserved for future use, must be 0 u32 padding1; ///< Reserved for future use, must be 0 } GX2DisplayListOverrun; /// \brief Prototype for GX2 (interrupt) callback functions. /// /// \param event The event which resulted in this callback. /// \param userDataPtr The user data pointer which was provided when the callback was set up. /// typedef void (*GX2CallbackFunction)(GX2CallbackEvent event, void *userDataPtr); /// \brief Set up a callback for a GX2 event. /// /// \param event The event that this callback will handle. /// \param functionPtr A pointer to the callback function. /// \param userDataPtr A pointer which will be passed to the callback when the event occurs. /// /// \note The \ref GX2_CB_EVENT_USER_TS_BOTTOM event shares an interrupt that /// is also used by the command-buffer-management code. The callback will /// also get called for each command buffer or direct display list that /// is sent to the GPU. The callback will need to look at the returned /// timestamp and compare with the previous one to determine if the event /// was triggered by a user time stamp or a system one. /// /// \note If you set the \ref GX2_CB_EVENT_USER_TS_BOTTOM callback, you will /// also disable an optimization to ignore (mask) bottom-of-pipe /// interrupts until the command-buffer-management code actually cares /// about them. Set the callback to NULL when it is not being used to /// reenable this optimization. /// /// \note If you set the \ref GX2_CB_EVENT_DL_OVERRUN callback, you must specify /// a valid \p userDataPtr that begins with the structure /// \ref GX2DisplayListOverrun. When the callback is invoked, the /// application must update this structure to point to a new display list /// to be used for future GX2 API calls. During this callback it is /// \b forbidden to call any GX2 APIs as this may result in a recursive /// call to the callback. For more information see /// \ref GX2DisplayListOverrun. /// /// \warning Failing to set the \ref GX2_CB_EVENT_DL_OVERRUN callback or failure /// to provide a valid display list before exiting the callback /// function will result in an OSPanic error being invoked if a /// display list buffer overrun occurs. /// /// \warning Display lists generated using the overrun callback must be /// called sequentially. /// /// \donotcall \gx2_typical \enddonotcall /// void GX2API GX2SetEventCallback(GX2CallbackEvent event, GX2CallbackFunction functionPtr, void *userDataPtr); /// \brief Get info about callback for a GX2 event. /// /// \param event The event that the callback handles. /// \param functionPtr A return pointer for the callback function pointer. /// \param userDataPtr A return pointer for the user-provided data pointer. /// /// \donotcall \threadsafe \devonly \enddonotcall /// void GX2API GX2GetEventCallback(GX2CallbackEvent event, GX2CallbackFunction *functionPtr, void **userDataPtr); /// \brief Request the GPU to write out a user time stamp. /// /// When the GPU reaches the indicated event, it will write out /// the timeStampValue to the given tsBuffer location. If /// requested, it can also trigger an interrupt callback request. /// /// \note Please see \ref GX2SetEventCallback for notes regarding the /// GX2_CB_EVENT_USER_TS_BOTTOM event. /// /// \note The time stamp value is written with the lower 32 bits first /// (due to hardware limitations). The value must not be written to a /// cacheline that is shared with any CPU-written data. /// /// \param tsBuffer A pointer for where the time stamp value will be written. /// \param timeStampValue The time stamp value to write when the event occurs. /// \param when The point in time at which to write the time stamp. /// \param triggerIntCB A boolean indicating if the event should trigger an interrupt callback. /// /// \donotcall \gx2_typical \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2SubmitUserTimeStamp(u64 *tsBuffer, u64 timeStampValue, GX2PipeEvent when, GX2Boolean triggerIntCB); /// \brief Helper function to properly read a user timestamp value. /// /// \param tsBuffer The pointer to the time stamp buffer. /// \return The value in the time stamp buffer. /// /// \donotcall \notthreadsafe \devonly \enddonotcall /// GX2_INLINE u64 GX2ReadUserTimeStamp(u64 *tsBuffer) { // This will destroy any CPU-written data in the same cacheline: DCInvalidateRange((void *) tsBuffer, 32); return ((*tsBuffer)>>32) | ((*tsBuffer)<<32); } /// \brief Make GPU CP wait for ((*fencePtr & fenceMask) op fenceValue) before proceeding. /// /// The wait is done at the top of the pipeline. An operation of GX2_COMPARE_NEVER is not allowed /// (it would hang the GPU). /// /// \param fencePtr Pointer to the u32 value the GPU should read. /// \param fenceMask The read value is anded with this mask first. /// \param op The type of compare operation to perform. /// \param fenceValue The value to be compared with. /// /// \donotcall \gx2_typical \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2SetGPUFence(u32 *fencePtr, u32 fenceMask, GX2CompareFunction op, u32 fenceValue); // ---- /// \brief Initialize GX2 semaphore. /// /// This is a helper function to initialise the semaphore for syncronize GPU7 with DMA Engine. /// The semaphore value is kept in memory at the given location. /// It is initialized to a given count and flushed from the cache. /// This API has exactly the same functional capability as \ref DMAEInitSemaphore. /// /// \param semaphoreAddr Location of semaphore data in memory /// \param semaphoreCount Initial semaphore count /// /// \donotcall \notthreadsafe \devonly \enddonotcall /// GX2_INLINE void GX2InitSemaphore(u64 *semaphoreAddr, u64 semaphoreCount) { // Store u64 byte-reversed (hardware requirement) * (__bytereversed u64 *) semaphoreAddr = semaphoreCount; DCFlushRange(semaphoreAddr, sizeof(u64)); } /// \brief Have GPU7 wait on or signal a memory semaphore. /// /// This function is used to syncronize the GPU with the DMA Engine. /// The semaphore value is kept in memory at the given location. /// It should be initialized and flushed from the cache before use. /// /// \param semaphoreAddr Location of semaphore data in memory /// \param semaphoreAction Indicates whether to wait on or signal the semaphore /// /// \donotcall \gx2_typical \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2SetSemaphore(u64 *semaphoreAddr, GX2SemaphoreAction semaphoreAction); /// @} /// @addtogroup GX2ManagementResetGroup /// @{ /// \brief Set a new value for various GX2 miscellaneous system parameters. /// /// This function is a general entry point for setting various GX2 parameters. /// These parameters relate to GPU reset at the moment, but might be extended to /// other types of functionality in the future. /// /// The available parameters are: /// - GX2_MISC_HANG_STATE: indicates if GPU is hung; returns: /// - GX2_HANG_STATE_OK: GPU is okay. /// - GX2_HANG_STATE_TS: time-out waiting for timestamp or GX2DrawDone. /// - GX2_HANG_STATE_CB: time-out waiting for command buffer space. /// - GX2_HANG_STATE_RB: time-out waiting for ring buffer space. /// - GX2_HANG_STATE_WF: time-out waiting for scan buffer flip (GX2WaitForFlip). /// - GX2_HANG_STATE_ETC: a named value that the user may set to indicate a hang. /// - GX2_MISC_HANG_RESPONSE: indicates response to GPU time-out (hang). /// Default is set based on production/development mode setting: /// - GX2_HANG_RESPONSE_NONE: set hang state & otherwise do nothing (reset will be done by user code). /// - GX2_HANG_RESPONSE_DEBUG: dump debug output and wait (Development default). /// - GX2_HANG_RESPONSE_RESET: set hang state & enable automatic reset at swap buffer time (Production default). /// (other values reserved for future behaviors). /// Automatic reset, if enabled, may occur during GX2SwapScanBuffers; /// it is triggered by the time-outs above or by a combination of these two: /// - GX2_MISC_HANG_RESET_SWAP_TIMEOUT: number of milliseconds since last swap before a hang is indicated; /// (both time & count conditions must be met before a hang is indicated) /// - GX2_MISC_HANG_RESET_SWAP_COUNT: number of frames waiting in the pipeline before a hang is indicated /// (both time & count conditions must be met before a hang is indicated) /// /// \returns true if parameter/value pair is valid; false otherwise. /// /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall /// GX2Boolean GX2API GX2SetMiscParam(GX2MiscType param, u32 value); /// \brief Get the value for various GX2 miscellaneous system parameters. /// /// See \ref GX2SetMiscParam for a list of possible parameters and values. /// /// \return The value of the requested parameter, or 0xffffffff for bad parameter value. /// /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall /// u32 GX2API GX2GetMiscParam(GX2MiscType param); /// \brief Reset the GPU. /// /// \param reserved Reserved for future use; set to 0 for now. /// /// \donotcall \nomulticore \gx2_dl \enddonotcall /// /// \clobberstate /// /// \writesgpu /// \directwritesgpu /// void GX2API GX2ResetGPU(u32 reserved); /// @} /// @addtogroup GX2ManagementDLGroup /// @{ /// \brief Create a display list that can be executed later. /// \note The memory in pDisplayList will be written to by the write-gatherer and needs to be /// flushed from CPU cache with GX2Invalidate() before using. /// \note The maximum display list size is 0xfffff u32's, or 4M-4 bytes. /// /// \param pDisplayList pointer to a buffer to hold the display list data. /// \param byteSize the size of the display list buffer in bytes. /// \param enableProfiling Initial profiling state for the display list /// /// \note The memory used for pDisplayList must be allocated from MEM2 using /// an API such as MEMAllocFromDefaultHeapEx. /// /// \note The memory used for pDisplayList must be allocated from MEM2 only. /// You cannot create display lists in MEM1. /// /// \note The memory used for pDisplayList must be aligned to \ref GX2_DISPLAY_LIST_ALIGNMENT. /// /// \note The profiling state is stored with the state context so if GX2SetContextState is called /// within the display list the profiling state (enabled or disabled) may change. /// If GX2SetContextState() is not called in the display list the correct context state /// (with respect to profiling) must be set before calling GX2CallDisplayList() or /// GX2DirectCallDisplayList() to execute the display list. /// /// \donotcall \gx2_dl \enddonotcall /// void GX2API GX2BeginDisplayListEx(void* pDisplayList, u32 byteSize, GX2Boolean enableProfiling); /// \brief Create a display list that can be executed later. /// \note The memory in pDisplayList will be written to by the write-gatherer and needs to be /// flushed from CPU cache with GX2Invalidate() before using. /// \note The maximum display list size is 0xfffff u32's, or 4M-4 bytes. /// /// \param pDisplayList pointer to a buffer to hold the display list data. /// \param byteSize the size of the display list buffer in bytes. /// /// \note The memory used for pDisplayList must be allocated from MEM2 using /// an API such as MEMAllocFromDefaultHeapEx. /// /// \note The memory used for pDisplayList must be allocated from MEM2 only. /// You cannot create display lists in MEM1. /// /// \note The memory used for pDisplayList must be aligned to \ref GX2_DISPLAY_LIST_ALIGNMENT. /// /// \note HW Profiling will be enabled for the Display list /// /// \donotcall \gx2_dl \enddonotcall /// GX2_INLINE void GX2BeginDisplayList(void* pDisplayList, u32 byteSize) { GX2BeginDisplayListEx(pDisplayList, byteSize, GX2_ENABLE); } /// \brief End the display list generation. /// /// \param pDisplayList pointer to the display list buffer. /// \return the actual size of the display list in bytes. /// /// \donotcall \gx2_typical \enddonotcall /// u32 GX2API GX2EndDisplayList(void* pDisplayList); /// \brief Execute the displaylist by adding it directly to the graphics ring buffer. /// \note This function can only be called from the main thread. /// /// \param pDisplayList pointer to the display list buffer. /// \param byteSize the size of the display list in bytes. /// /// \note pDisplayList must aligned by GX2_DISPLAY_LIST_ALIGNMENT. /// /// \donotcall \nomulticore \gx2_dl \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2DirectCallDisplayList(void* pDisplayList, u32 byteSize); /// \brief Execute the displaylist by adding it to the current display list or command buffer. /// \note A display list referenced in this call cannot call another display list (no nesting). /// /// \param pDisplayList pointer to the display list buffer. /// \param byteSize the size of the display list in bytes. /// /// \note pDisplayList must be aligned by GX2_DISPLAY_LIST_ALIGNMENT. /// /// \donotcall \gx2_typical \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2CallDisplayList(void* pDisplayList, u32 byteSize); /// \brief Get status of whether we're currently writing to a display list or not. /// /// \return GX2_TRUE if we are currently in between GX2BeginDisplayList/GX2EndDisplayList, else GX2_FALSE. /// /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall /// GX2Boolean GX2API GX2GetDisplayListWriteStatus(void); /// \brief Get information about the current display list being made. /// /// \note If you are not currently making a display list, the parameters are ignored /// and GX2_FALSE is returned. /// /// \note If an input pointer is NULL, it is ignored. /// /// \param ppDisplayList pointer to hold result for the current display list pointer. /// \param pByteSizeMax pointer to hold result for the max size of the display list in bytes. /// /// \return GX2_TRUE if we are currently in between GX2BeginDisplayList/GX2EndDisplayList, else GX2_FALSE. /// /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall /// GX2Boolean GX2API GX2GetCurrentDisplayList(void **ppDisplayList, u32 *pByteSizeMax); /// \brief Copy a display list buffer into the current display list. /// /// This API will copy each command from pDisplayList into the current /// display list or command buffer. /// /// \note After calling this API, pDisplayList will be in the CPU cache. /// Before pDisplayList is used by \ref GX2CallDisplayList or /// \ref GX2DirectCallDisplayList it is best to flush it from the CPU /// cache. /// /// \param pDisplayList Ptr to a display list; should be aligned by GX2_DISPLAY_LIST_ALIGNMENT. /// \param byteSize Size of the display list in bytes; should be a multiple of 4. /// /// \donotcall \gx2_typical \enddonotcall /// /// \writesgpu /// \alwayswritesgpu /// void GX2API GX2CopyDisplayList(void * pDisplayList, u32 byteSize); /// @} /// @} #ifdef __cplusplus } #endif // __cplusplus #endif // _CAFE_GX2_MANAGE_H_