Nugget
|
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 () |
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.
|
strong |
|
strong |
|
strong |
|
strong |
|
strong |
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.
period | The period of the timer in microseconds. |
callback | The callback function to be called when the timer expires. |
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.
deadline | The deadline of the timer in microseconds. |
callback | The callback function to be called when the timer expires. |
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.
id | The id of the timer to cancel. |
|
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.
fragment | The fragment to chain. |
|
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.
first | The pointer to the first fragment of the chain. |
last | The pointer to the last fragment of the chain. |
|
inline |
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.
id | The id of the timer to change. |
period | The new period of the timer. |
reset | The timer's deadline will be adjusted to the new period if false. |
Immediately clears the drawing buffer.
This method will immediately clear the drawing buffer with the specified color.
bg | The color to fill the drawing buffer with. |
|
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.
amount | The amount of time to delay the coroutine in microseconds. |
co_await
keyword. void psyqo::GPU::disableScissor | ( | ) |
Immediately disables the scissoring of the VRAM.
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.
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.
ff | The FastFill primitive to set. |
end | The color to issue. |
|
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.
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.
ff | The FastFill primitive to set. |
end | The color to issue. |
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.
scissor | The scissor primitive to set. |
|
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.
|
inline |
Returns the refresh rate of the GPU.
This method will return either 60 or 50, depending on the current video mode.
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.
scissor | The scissor primitive to set. |
void psyqo::GPU::initialize | ( | const Configuration & | config | ) |
bool psyqo::GPU::isChainIdle | ( | ) | const |
bool psyqo::GPU::isChainTransferred | ( | ) | const |
bool psyqo::GPU::isChainTransferring | ( | ) | 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()
.
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.
id | The id of the timer to pause. |
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.
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.
id | The id of the timer to resume. |
void psyqo::GPU::sendChain | ( | ) |
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.
callback | The callback to call upon completion. |
dmaCallback | DMA::FROM_MAIN_LOOP or DMA::FROM_ISR . |
|
inline |
Immediately sends a fragment to the GPU. This is a blocking operation. See the fragments.hh file for more information.
fragment | The fragment to send to the GPU. |
|
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.
fragment | The fragment to send to the GPU. |
callback | The callback to call upon completion. |
dmaCallback | DMA::FROM_MAIN_LOOP or DMA::FROM_ISR . |
|
inline |
Sends a raw 32 bits value to the Data register of the GPU.
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.
data | The 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. |
region | The region in VRAM to upload the pixels to. |
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.
data | The 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. |
region | The region in VRAM to upload the pixels to. |
callback | The callback to call upon completion. |
dmaCallback | DMA::FROM_MAIN_LOOP or DMA::FROM_ISR . |
|
inline |
Waits until the background DMA transfer operation initiated by a frame flip is complete.
|
friend |
|
friend |
|
staticconstexpr |
|
staticconstexpr |