Nugget
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Friends | List of all members
psyqo::GPU Class Reference

The singleton GPU class. More...

#include <psyqo/gpu.hh>

Classes

struct  Configuration
 

Public Types

enum class  Resolution {
  W256 , W320 , W368 , W512 ,
  W640
}
 
enum class  VideoMode { AUTO , NTSC , PAL }
 
enum class  ColorMode { C15BITS , C24BITS }
 
enum class  Interlace { PROGRESSIVE , INTERLACED }
 
enum class  MiscSetting { CLEAR_VRAM , KEEP_VRAM }
 

Public Member Functions

void initialize (const Configuration &config)
 
unsigned getRefreshRate () const
 Returns the refresh rate of the GPU.
 
uint32_t getFrameCount () const
 Returns the number of frames rendered by the GPU so far.
 
unsigned getParity () const
 Get the index of the current display buffer.
 
void clear (Color bg={{0, 0, 0}})
 Immediately clears the drawing buffer.
 
void getClear (Prim::FastFill &ff, Color bg={{0, 0, 0}}) const
 Sets a FastFill primitive to clear the current drawing buffer.
 
void getNextClear (Prim::FastFill &ff, Color bg={{0, 0, 0}}) const
 Sets a FastFill primitive to clear the next drawing buffer.
 
void uploadToVRAM (const uint16_t *data, Rect region)
 Uploads a buffer to the VRAM as a blocking call.
 
void uploadToVRAM (const uint16_t *data, Rect region, eastl::function< void()> &&callback, DMA::DmaCallback dmaCallback=DMA::FROM_MAIN_LOOP)
 Uploads a buffer to the VRAM as a non-blocking call.
 
template<Fragment Frag>
void sendFragment (const Frag &fragment)
 Immediately sends a fragment to the GPU. This is a blocking operation. See the fragments.hh file for more information.
 
template<Fragment Frag>
void sendFragment (const Frag &fragment, eastl::function< void()> &&callback, DMA::DmaCallback dmaCallback=DMA::FROM_MAIN_LOOP)
 Sends a fragment to the GPU as a non-blocking call.
 
void disableScissor ()
 Immediately disables the scissoring of the VRAM.
 
void enableScissor ()
 Enables the scissoring of the VRAM.
 
void getScissor (Prim::Scissor &scissor)
 Gets the current scissoring region.
 
void getNextScissor (Prim::Scissor &scissor)
 Gets the next scissoring region.
 
void waitReady ()
 Waits until the GPU is ready to send a command.
 
void waitFifo ()
 Waits until the GPU's FIFO is ready to receive data.
 
template<Primitive Prim>
void sendPrimitive (const Prim &primitive)
 Sends a primitive to the GPU. This is a blocking call.
 
template<Fragment Frag>
void chain (Frag &fragment)
 Chains a fragment to the next DMA chain transfer.
 
template<Fragment Frag1, Fragment Frag2>
void chain (Frag1 *first, Frag2 *last)
 Chains an already constructed DMA chain to the next DMA chain transfer.
 
template<size_t N, Safe safety = Safe::Yes>
void chain (OrderingTable< N, safety > &table)
 Chains an ordering table to the next DMA chain transfer.
 
void sendChain ()
 Immediately sends the current DMA chain.
 
void sendChain (eastl::function< void()> &&callback, DMA::DmaCallback dmaCallback=DMA::FROM_MAIN_LOOP)
 Initiates the transfer of the current DMA chain.
 
bool isChainIdle () const
 Gets the status of the background DMA transfer operation when initiated by a frame flip.
 
bool isChainTransferring () const
 Gets the status of the background DMA transfer operation when initiated by a frame flip.
 
bool isChainTransferred () const
 Gets the status of the background DMA transfer operation when initiated by a frame flip.
 
void waitChainIdle ()
 Waits until the background DMA transfer operation initiated by a frame flip is complete.
 
uint32_t now () const
 Gets the current timestamp in microseconds.
 
uintptr_t armTimer (uint32_t deadline, eastl::function< void(uint32_t)> &&callback)
 Creates a single-use timer.
 
TimerAwaiter delay (uint32_t microseconds)
 Delays the coroutine for a specified amount of time.
 
unsigned armPeriodicTimer (uint32_t period, eastl::function< void(uint32_t)> &&callback)
 Creates a periodic timer.
 
void changeTimerPeriod (uintptr_t id, uint32_t period, bool reset=false)
 Changes the period of a periodic timer.
 
void pauseTimer (uintptr_t id)
 Pauses a timer.
 
void resumeTimer (uintptr_t id)
 Resumes a paused timer.
 
void cancelTimer (uintptr_t id)
 Cancels a timer.
 
void pumpCallbacks ()
 Runs one round of event processing.
 

Static Public Member Functions

static void sendRaw (uint32_t data)
 Sends a raw 32 bits value to the Data register of the GPU.
 

Static Public Attributes

static constexpr uint32_t US_PER_HBLANK = 64
 
static constexpr unsigned c_chainThreshold = 56
 

Friends

class Application
 
void psyqo::Kernel::takeOverKernel ()
 

Detailed Description

The singleton GPU class.

This class shouldn't be instantiated directly. It is a singleton instantiated within the Application class, and accessed using the gpu method. It contains the current state of the psyqo renderer, and provides various helpers for rendering.

Member Enumeration Documentation

◆ ColorMode

enum class psyqo::GPU::ColorMode
strong
Enumerator
C15BITS 
C24BITS 

◆ Interlace

enum class psyqo::GPU::Interlace
strong
Enumerator
PROGRESSIVE 
INTERLACED 

◆ MiscSetting

enum class psyqo::GPU::MiscSetting
strong
Enumerator
CLEAR_VRAM 
KEEP_VRAM 

◆ Resolution

enum class psyqo::GPU::Resolution
strong
Enumerator
W256 
W320 
W368 
W512 
W640 

◆ VideoMode

enum class psyqo::GPU::VideoMode
strong
Enumerator
AUTO 
NTSC 
PAL 

Member Function Documentation

◆ armPeriodicTimer()

uintptr_t psyqo::GPU::armPeriodicTimer ( uint32_t  period,
eastl::function< void(uint32_t)> &&  callback 
)

Creates a periodic timer.

This method will create a periodic timer. The timer will fire every period microseconds. See the armTimer method for more information about timers in general. Periodic timers will first fire at now() + period microseconds, and then every period microseconds thereafter. They will never be canceled automatically.

Parameters
periodThe period of the timer in microseconds.
callbackThe callback function to be called when the timer expires.
Returns
The id of the created timer.

◆ armTimer()

uintptr_t psyqo::GPU::armTimer ( uint32_t  deadline,
eastl::function< void(uint32_t)> &&  callback 
)

Creates a single-use timer.

This method will create a single-use timer. The timer will fire after the specified deadline has passed. Timers will only fire during the idle period of the CPU, for example during calls to sendFragment, or between calls to the frame method of the current scene. If the scene takes too long to compute, timers may significantly be delayed past their set deadline. The deadline can be computed based on the return value of the now() method. It is okay if the deadline rolls over their 32 bits span. Simply doing gpu().now() + DELAY_IN_MICROSECONDS will still work, as long as the delay isn't greater than 30 minutes. Single-use timers will automatically be disabled upon being fired, and their id will no longer be valid. The returned id is guaranteed to be unique across active timers, but may collision with the id of timers that got canceled or got disabled on their own.

Parameters
deadlineThe deadline of the timer in microseconds.
callbackThe callback function to be called when the timer expires.
Returns
The id of the created timer.

◆ cancelTimer()

void psyqo::GPU::cancelTimer ( uintptr_t  id)

Cancels a timer.

This method will cancel an active timer. The timer will no longer fire. Its id will no longer be valid.

Parameters
idThe id of the timer to cancel.

◆ chain() [1/3]

template<Fragment Frag>
void psyqo::GPU::chain ( Frag &  fragment)
inline

Chains a fragment to the next DMA chain transfer.

This method will chain a fragment to the next DMA chain transfer. DMA Chaining is a complex operation, and it is recommended that you use the sendFragment method instead if you are unsure. This can be used while a DMA chain is being sent. Use the sendChain method to transfer the DMA chain during the current frame, or simply return from the current scene's frame method to transfer the DMA chain automatically during the frame flip operation. Note that the latter means the DMA chain will render on the next rendered frame, thus creating a sort of triple buffering system. The constructed DMA chain will thus need to be using the Next variants of the primitive constructors, if applicable.

Parameters
fragmentThe fragment to chain.

◆ chain() [2/3]

template<Fragment Frag1, Fragment Frag2>
void psyqo::GPU::chain ( Frag1 *  first,
Frag2 *  last 
)
inline

Chains an already constructed DMA chain to the next DMA chain transfer.

This method will chain an already constructed DMA chain to the next DMA chain transfer. This is an even more complex operation than the previous chain method, as it requires the user to construct the DMA chain manually. Some helpers are provided in the Fragments namespace.

Parameters
firstThe pointer to the first fragment of the chain.
lastThe pointer to the last fragment of the chain.

◆ chain() [3/3]

template<size_t N, Safe safety = Safe::Yes>
void psyqo::GPU::chain ( OrderingTable< N, safety > &  table)
inline

Chains an ordering table to the next DMA chain transfer.

This method will chain an ordering table to the next DMA chain transfer. The ordering table table will be cleared automatically after the transfer is complete.

Parameters
tableThe ordering table to chain.

◆ changeTimerPeriod()

void psyqo::GPU::changeTimerPeriod ( uintptr_t  id,
uint32_t  period,
bool  reset = false 
)

Changes the period of a periodic timer.

This method will change the period of a periodic timer. The timer now will fire every period microseconds instead of its previous period. When the reset argument is false, the next deadline for the timer will be adjusted according to the difference between the new period and the previous one. If the new period is shorter, and the deadline goes in the past, the timer will fire as soon as possible. When the reset argument is true, the new deadline will simply be set to the new period. This method has no effect if the timer is not periodic.

Parameters
idThe id of the timer to change.
periodThe new period of the timer.
resetThe timer's deadline will be adjusted to the new period if false.

◆ clear()

void psyqo::GPU::clear ( Color  bg = {{0, 0, 0}})

Immediately clears the drawing buffer.

This method will immediately clear the drawing buffer with the specified color.

Parameters
bgThe color to fill the drawing buffer with.

◆ delay()

TimerAwaiter psyqo::GPU::delay ( uint32_t  microseconds)
inline

Delays the coroutine for a specified amount of time.

This method will delay the coroutine for a specified amount of time. This is a coroutine-friendly version of the armTimer method. The coroutine will be suspended until the delay has passed. The delay is specified in microseconds, and the timer literals can be used to specify the delay. The function can only be called from within a coroutine, and is meant to be used with the co_await keyword.

Parameters
amountThe amount of time to delay the coroutine in microseconds.
Returns
TimerAwaiter The awaitable object to be used with the co_await keyword.

◆ disableScissor()

void psyqo::GPU::disableScissor ( )

Immediately disables the scissoring of the VRAM.

◆ enableScissor()

void psyqo::GPU::enableScissor ( )

Enables the scissoring of the VRAM.

This method will enable the scissoring of the VRAM, and will clip the drawing to the currently active buffer.

◆ getClear()

void psyqo::GPU::getClear ( Prim::FastFill ff,
Color  bg = {{0, 0, 0}} 
) const

Sets a FastFill primitive to clear the current drawing buffer.

This method will set the FastFill primitive passed as an argument in a way to completely clear the current drawing buffer with the specified color. This will be done in accordance to the current drawing buffer settings.

Parameters
ffThe FastFill primitive to set.
endThe color to issue.

◆ getFrameCount()

uint32_t psyqo::GPU::getFrameCount ( ) const
inline

Returns the number of frames rendered by the GPU so far.

This returns the internal frame counter being kept by the GPU class. The 32 bits value will wrap around when it reaches 2^32 frames, which is 2 years, 3 months, 7 days, 6 hours, 6 minutes and 28.27 seconds when running constantly at a 60Hz refresh rate. This counter will be incremented during the frame flip operation by the appropriate number of hardware frames which have passed since the last frame flip. In other words, this counter monotonically increases by one for each vsync event that occurred during the last rendering.

◆ getNextClear()

void psyqo::GPU::getNextClear ( Prim::FastFill ff,
Color  bg = {{0, 0, 0}} 
) const

Sets a FastFill primitive to clear the next drawing buffer.

This method will set the FastFill primitive passed as an argument in a way to completely clear the next drawing buffer with the specified color. This will be done in accordance to the next drawing buffer settings, after a flip. This is useful for clearing the buffer within a dma chain to be sent during the frame flip.

Parameters
ffThe FastFill primitive to set.
endThe color to issue.

◆ getNextScissor()

void psyqo::GPU::getNextScissor ( Prim::Scissor scissor)

Gets the next scissoring region.

This method will set the scissor primitive to the next active drawing buffer. This is useful for setting the scissor within a dma chain to be sent during the frame flip.

Parameters
scissorThe scissor primitive to set.

◆ getParity()

unsigned psyqo::GPU::getParity ( ) const
inline

Get the index of the current display buffer.

This method will return the index of the current display buffer. The index will be either 0 or 1, and will be updated during the frame flip operation. This is useful for double buffering: when designing an application which uses double buffering, the application should keep two sets of data, one for each display buffer. The application should then use the getParity method to determine which if its two sets of data should be used for the current frame.

Returns
unsigned The index of the current display buffer, either 0 or 1.

◆ getRefreshRate()

unsigned psyqo::GPU::getRefreshRate ( ) const
inline

Returns the refresh rate of the GPU.

This method will return either 60 or 50, depending on the current video mode.

◆ getScissor()

void psyqo::GPU::getScissor ( Prim::Scissor scissor)

Gets the current scissoring region.

This method will set the scissor primitive to the currently active drawing buffer.

Parameters
scissorThe scissor primitive to set.

◆ initialize()

void psyqo::GPU::initialize ( const Configuration config)

◆ isChainIdle()

bool psyqo::GPU::isChainIdle ( ) const

Gets the status of the background DMA transfer operation when initiated by a frame flip.

Returns
true if no background DMA transfer is in progress nor completed.

◆ isChainTransferred()

bool psyqo::GPU::isChainTransferred ( ) const

Gets the status of the background DMA transfer operation when initiated by a frame flip.

Returns
true if a background DMA transfer has completed, and is now waiting for a frame flip.

◆ isChainTransferring()

bool psyqo::GPU::isChainTransferring ( ) const

Gets the status of the background DMA transfer operation when initiated by a frame flip.

Returns
true if a background DMA transfer is in progress.

◆ now()

uint32_t psyqo::GPU::now ( ) const
inline

Gets the current timestamp in microseconds.

The current timestamp is in microseconds. It will wrap around after a bit more than an hour, so it shouldn't be used for deadlines that are more than 30 minutes away. This relies on root counter 1 set in hsync mode without any target value. The value will be updated during the idle moments of the page flip, without relying on interrupts. The precision isn't really good, as it assumes one scanline runs at 64us, but it should be good enough for most purposes. Creating a stopwatch out of it should show that it's running a bit too fast, approximately 1 second too fast every minute or so. Its monotonicity should be proper however.

The method now() should be reserved for interacting with timers. If longer span is required, with more accuracy but less precision, for something that's not related with timers, then the current amount of time in seconds since the application started can simply be obtained using getFrameCount() / getRefreshRate().

Returns
The current timestamp in microseconds.

◆ pauseTimer()

void psyqo::GPU::pauseTimer ( uintptr_t  id)

Pauses a timer.

This method will pause a timer. It will not fire anymore, even if its deadline had already passed at the moment of this call, but it will remain active, and its id will remain valid. The remainder of the deadline will be remembered, for when the timer is resumed. This method has no effect if the timer is already paused.

Parameters
idThe id of the timer to pause.

◆ pumpCallbacks()

void psyqo::GPU::pumpCallbacks ( )

Runs one round of event processing.

While this method is technically for internal use, it is exposed here for convenience. It will run one round of event processing, including the processing of timers. This method should be called in a loop when waiting for other events to be processed.

◆ resumeTimer()

void psyqo::GPU::resumeTimer ( uintptr_t  id)

Resumes a paused timer.

This method will resume a paused timer. The timer will be able to fire again, according to its original settings. The new deadline will be calculated from the remainder of the time left when it was paused. This method will have no effect if the timer is not paused.

Parameters
idThe id of the timer to resume.

◆ sendChain() [1/2]

void psyqo::GPU::sendChain ( )

Immediately sends the current DMA chain.

This method will immediately send the current DMA chain to the GPU, and block until completion.

◆ sendChain() [2/2]

void psyqo::GPU::sendChain ( eastl::function< void()> &&  callback,
DMA::DmaCallback  dmaCallback = DMA::FROM_MAIN_LOOP 
)

Initiates the transfer of the current DMA chain.

See the non-blocking variant of uploadToVRAM for more information about asynchronous transfers.

Parameters
callbackThe callback to call upon completion.
dmaCallbackDMA::FROM_MAIN_LOOP or DMA::FROM_ISR.

◆ sendFragment() [1/2]

template<Fragment Frag>
void psyqo::GPU::sendFragment ( const Frag &  fragment)
inline

Immediately sends a fragment to the GPU. This is a blocking operation. See the fragments.hh file for more information.

Parameters
fragmentThe fragment to send to the GPU.

◆ sendFragment() [2/2]

template<Fragment Frag>
void psyqo::GPU::sendFragment ( const Frag &  fragment,
eastl::function< void()> &&  callback,
DMA::DmaCallback  dmaCallback = DMA::FROM_MAIN_LOOP 
)
inline

Sends a fragment to the GPU as a non-blocking call.

See the non-blocking variant of uploadToVRAM for more information about asynchronous transfers.

Parameters
fragmentThe fragment to send to the GPU.
callbackThe callback to call upon completion.
dmaCallbackDMA::FROM_MAIN_LOOP or DMA::FROM_ISR.

◆ sendPrimitive()

template<Primitive Prim>
void psyqo::GPU::sendPrimitive ( const Prim &  primitive)
inline

Sends a primitive to the GPU. This is a blocking call.

This method will immediately send the specified primitive to the GPU.

Parameters
primitiveThe primitive to send to the GPU.

◆ sendRaw()

static void psyqo::GPU::sendRaw ( uint32_t  data)
inlinestatic

Sends a raw 32 bits value to the Data register of the GPU.

◆ uploadToVRAM() [1/2]

void psyqo::GPU::uploadToVRAM ( const uint16_t *  data,
Rect  region 
)

Uploads a buffer to the VRAM as a blocking call.

This method will immediately upload the specified set of pixels to the VRAM, at the specified location and size. The GPU cache will be flushed. It will block until completion of the upload.

Parameters
dataThe pixels to upload. Must be a contiguous array of 16-bpp pixels, with the number of pixels being equal to the area specified by the region parameter.
regionThe region in VRAM to upload the pixels to.

◆ uploadToVRAM() [2/2]

void psyqo::GPU::uploadToVRAM ( const uint16_t *  data,
Rect  region,
eastl::function< void()> &&  callback,
DMA::DmaCallback  dmaCallback = DMA::FROM_MAIN_LOOP 
)

Uploads a buffer to the VRAM as a non-blocking call.

This method will initiate an upload of the specified set of pixels to the VRAM, at the specified location and size. The GPU cache will be flushed. It will return immediately, and the upload will be performed in the background. Upon completion, the specified callback will be called. If dmaCallback is set to FROM_ISR, the callback will be called from the interrupt handler, and care must be taken to properly synchronize variable changes. Please use the EASTL's atomic_signal_fence function for this purpose. If dmaCallback is set to FROM_MAIN_LOOP, the callback will be called in the same execution context as the main loop, and it is therefore safe to access variables there. The callback will thus be called between calls to the current scene's frame method, or during Kernel::pumpCallbacks(). Note that during the upload, no GPU operation should be performed.

Parameters
dataThe pixels to upload. Must be a contiguous array of 16-bpp pixels, with the number of pixels being equal to the area specified by the region parameter.
regionThe region in VRAM to upload the pixels to.
callbackThe callback to call upon completion.
dmaCallbackDMA::FROM_MAIN_LOOP or DMA::FROM_ISR.

◆ waitChainIdle()

void psyqo::GPU::waitChainIdle ( )
inline

Waits until the background DMA transfer operation initiated by a frame flip is complete.

◆ waitFifo()

void psyqo::GPU::waitFifo ( )

Waits until the GPU's FIFO is ready to receive data.

◆ waitReady()

void psyqo::GPU::waitReady ( )

Waits until the GPU is ready to send a command.

Friends And Related Symbol Documentation

◆ Application

friend class Application
friend

◆ psyqo::Kernel::takeOverKernel

Member Data Documentation

◆ c_chainThreshold

constexpr unsigned psyqo::GPU::c_chainThreshold = 56
staticconstexpr

◆ US_PER_HBLANK

constexpr uint32_t psyqo::GPU::US_PER_HBLANK = 64
staticconstexpr

The documentation for this class was generated from the following files: