nn::gr::CTR::MakeChannel0SubroutineCommand Function

Syntax

bit32 * MakeChannel0SubroutineCommand(
     bit32 * command,
     uptr * bufferSizePtr,
     const uptr commandBufferPtr,
     const size_t commandBufferSize
);

Parameters

Name Description
in command The start address for storing the rendering command.
out bufferSizePtr The data address storing the byte size of the command buffer to execute after control returns from the jump destination.
in commandBufferPtr Address of the jump destination command buffer.
in commandBufferSize Byte size of the jump destination command buffer.

Return Values

Returns the address that follows the end of the stored rendering command.

Description

Adds a command set for jumping to a different command buffer (executed on Channel 0) and then returning control to the original command buffer.

For convenience, the jump destination command buffer is called a subroutine.

The value found by taking the number of bytes from the point of returning from the subroutine to the next channel kick command or split command (the command added using the nngxSplitDrawCmdlist function or nngxFlush3DCommand function) and dividing by 8 must be written into bufferSizePtr.

If the return value of this function is saved for later use, the number of bytes can be calculated based on the difference in the command buffer address immediately after the split command is added.

commandBufferPtr specifies the subroutine address, while commandbufferSize specifies the subroutine byte size. Both of these values must be a multiple of 16.

Example

    u32* command;
    u32* tmpHead;
    uptr sizeAddr;
    GLint bufSizeFirstKick;    // Stores the size from the start of the command buffer until the first channel kick command

    nngxGetCmdlistParameteri( NN_GX_CMDLIST_CURRENT_BUFADDR, reinterpret_cast< GLint* >( &command ) );
    const u32* startAddr = command;  // Keep the start address

    ...

    // In some cases, we will adjust the size of the command buffer (see below)

    command = MakeChannel1SubroutineCommand( command, &sizeAddr, subroutineAddr, subroutineSize );
    // Save the command buffer address immediately after adding the command set for making the jump
    tmpHead = command;
    bufSizeFirstKick = (command - startAddr) * sizeof(u32);

    ... // Generate the necessary commands

    // Advance the pointer to the render command buffer
    nngxMoveCommandbufferPointer( ( command - startAddr ) * sizeof(u32) );

    // Stop creating commands and add a split command
    // Specify the size from the start of the command buffer until the first channel kick command
    nngxFlush3DCommandPartially(bufSizeFirstKick);

    // Get the command buffer address after adding the split command
    nngxGetCmdlistParameteri( NN_GX_CMDLIST_CURRENT_BUFADDR, reinterpret_cast< GLint* >( &command ) );

    // Write the value given by taking the number of bytes from returning from the subroutine up to the split command and dividing by 8
    *(reinterpret_cast< u32* >(sizeAddr)) = ((command - tmpHead) * sizeof(u32)) >> 3;

    // Flush the cache
    // The nngxFlush3DCommandPartially function does not flush the cache for the command buffer, so:
    // We must perform this for the entire area.
    nngxUpdateBuffer( reinterpret_cast< u32* >(startAddr), (command - startAddr) * sizeof(u32) );

Make sure that the size of the buffer immediately after adding the command generated by this function is a multiple of 16. In some cases, you must adjust the size by generating a dummy command beforehand.

The byte size of commands added by this function is 24 bytes.

Also, a Channel 1 kick command must be stored at the end of command buffers specified as a subroutine.

Example: Adjusting the size of the command buffer

    bit32* AddDummyDataForCommandBuffer( bit32* command, const size_t size )
    {
        // Adjust so that the size of the buffer is a multiple of 16
        if ( size % 16 )
        {
            int num = (size >> 2) % 4;
            
            for ( int i=4; i>num; --i )
            {
                *command++ = 0;
            }
        }
        
        return command;
    }

    void CreateCommand(void)
    {
        u32* command;
        nngxGetCmdlistParameteri( NN_GX_CMDLIST_CURRENT_BUFADDR, reinterpret_cast< GLint* >( &command ) );

        const u32* startAddr = command;  // Keep the start address

        ... // Create command

        // In addition to the existing command buffer contents, the command size added by the MakeChannel0SubroutineCommand function
        // Assuming 24 bytes, add a dummy command so that the size is a multiple of 16
        command = AddDummyDataForCommandBuffer( command, (command - startAddr) * sizeof(u32) + 24 );

        // Adding the kick command makes the size of the command buffer an exact multiple of 16
        command = MakeChannel0SubroutineCommand( command, &sizeAddr, subroutineAddr, subroutineSize );

        ... // Create command
    }

See Also

nn::gr::CTR::MakeChannel1SubroutineCommand

Revision History

2011/10/20
Revised the code example, and added a code example demonstrating adjustment of the command buffer size.
2011/07/29
Initial version.

CONFIDENTIAL