Data Structures | |
struct | OSL_MEMSTATUS |
Defines | |
#define | oslUncacheData(data, size) sceKernelDcacheWritebackInvalidateRange(data, size); |
#define | oslGetUncachedPtr(adr) ((void*)((int)(adr)|0x40000000)) |
#define | oslGetCachedPtr(adr) ((void*)((int)(adr)&(~0x40000000))) |
Functions | |
int | sceDmacMemcpy (void *dest, const void *source, unsigned int size) |
int | sceDmacTryMemcpy (void *dest, const void *source, unsigned int size) |
void | oslFasterMemset (u64 *dst, u64 *src, u32 length) |
void | oslFlushDataCache () |
void * | memalign (size_t, size_t) |
OSL_MEMSTATUS | oslGetRamStatus () |
#define oslUncacheData | ( | data, | |||
size | ) | sceKernelDcacheWritebackInvalidateRange(data, size); |
This routine will make sure that the data will no more reside in the CPU cache. The CPU does automatically put data in cache when you want to read or write to it, making subsequent accesses faster (because the cache is way faster than conventional RAM). The problem is that if the GE (graphic processor) for example wants to access it, it will read the real memory, and thus if some data is still sitting in the cache (not written to actual RAM yet) the GE will get incorrect data, making it crash or display corrupt graphics.
To avoid problems, you can either bypass the cache by writting to uncached addresses (oslGetUncachedPtr) or by flushing the data from cache before sending them to the GE (or DMA). This function, oslUncacheData, will flush the actual data from cache, writing it to real memory. This does take some time so don't abuse and call it only when necessary.
data | Adress of the memory area to flush. | |
size | Size (in bytes) of the area. |
Note: There are specific functions to uncache palettes and images, simplier to use. You should rather use them instead.
#define oslGetUncachedPtr | ( | adr | ) | ((void*)((int)(adr)|0x40000000)) |
Returns a pointer to an uncached address. In this case, cache will be bypassed and you'll not have to call oslUncache[something] after modifying data. However performance is usually worse and caching is a good thing, so do it if you know what you are doing.
Important: NEVER mix cached and uncached addresses when accessing somewhere. Either always access them as cached or unached. If you mix them some weird bugs may appear because you could for example write directly in memory bypassing the cache, but some data is still sitting in the cache. So, once the cache is full, data will be flushed and written to the memory, replacing the data you wrote in an uncached way. You will not understand why your data gets corrupted, and as this will maybe happen seconds later in special circumstances, so it will be impossible to detect or debug.
#define oslGetCachedPtr | ( | adr | ) | ((void*)((int)(adr)&(~0x40000000))) |
Get a pointer to cached data. Same remark as above.
int sceDmacMemcpy | ( | void * | dest, | |
const void * | source, | |||
unsigned int | size | |||
) |
Copies data using the internal DMAC. Should be faster than a memcpy, but requires that data to be copied is no more in the cache, so usually you should issue a oslUncacheData on the source and destination addresses else very strange bugs may happen.
int sceDmacTryMemcpy | ( | void * | dest, | |
const void * | source, | |||
unsigned int | size | |||
) |
Same as sceDmacMemcpy.
void oslFasterMemset | ( | u64 * | dst, | |
u64 * | src, | |||
u32 | length | |||
) |
Does a memset using the 64-bit capabilities of the CPU. Faster than memcpy.
void oslFlushDataCache | ( | ) | [inline] |
Flushes the whole cache. This is slow, absolutely avoid it! Use oslUncacheData instead if possible.
void* memalign | ( | size_t | , | |
size_t | ||||
) |
Allocates a memory block, ensuring it is aligned.
1 | Alignment in bytes | |
2 | Size of the block |
OSL_MEMSTATUS oslGetRamStatus | ( | ) |
Gets info about currently available memory in main RAM. The return value is a OSL_MEMSTATUS structure which contains info about available memory.
Example:
//You can either store the result to a structure and access its members OSL_MEMSTATUS ram = oslGetRamStatus(); oslDebug("%i bytes available", ram.maxAvailable); //Or directly use the return value from the function, like this oslDebug("%i bytes available", oslGetRamStatus().maxAvailable);
Note: About the example above, just notice that each call to oslGetRamStatus costs a lot of time, so if you need to retrieve several results (e.g. both maxAvailable and maxBlockSize) you should not use the second method as it will need two calls to oslGetRamStatus.