See USE_SOFTWARE_CACHE in Bullet\src\BulletMultiThreaded\SpuNarrowPhaseCollisionTask\SpuGatheringCollisionTask.cpp It improves the Bullet midphase collision detection (triangle/vertex fetch) The license is CommonPublicLicense-1.0, see included license docs.
205 lines
5.3 KiB
C
205 lines
5.3 KiB
C
/*
|
|
* SCE CONFIDENTIAL
|
|
* PLAYSTATION(R)3 Programmer Tool Runtime Library 085.007
|
|
* Copyright (C) 2005 Sony Computer Entertainment Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* The SPU printf server is a PPU thread which collaborates with an SPU to
|
|
* output strings.
|
|
*
|
|
* On SPU-side, spu_printf() places the output string and arguments on a stack
|
|
* in the local storage, and passes its local-storage address with an SPU
|
|
* thread user event from SPU port 1 to PPU. On PPU-side,
|
|
* spu_thread_sprintf fetches the stack in the local stroage by DMA, and parse
|
|
* it to string-format.
|
|
*
|
|
* The SPU printf server takes charge of the tasks on PPU-side. The sequence
|
|
* of its task is as follows.
|
|
* 1. Receive events by sys_event_queue_receive()
|
|
* 2. Parse the received spu_printf stack address by spu_thread_snprintf.
|
|
* 3. Output the parsed string by printf(), and go back to step 1.
|
|
*
|
|
* Initialization of the SPU printf server and registeration of SPU threads to
|
|
* the SPU printf server is required. These can be done by
|
|
* spu_printf_server_initilize() and spu_printf_server_register().
|
|
* What they actually do is to create a PPU thread and event queue, and
|
|
* connect the SPU thread to the event queue.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <sys/ppu_thread.h>
|
|
#include <sys/spu_thread.h>
|
|
#include <sys/event.h>
|
|
#include <spu_printf.h>
|
|
#include "spu_printf_server.h"
|
|
|
|
#define STACK_SIZE 4096
|
|
#define PRIO 200
|
|
|
|
static sys_ppu_thread_t thread;
|
|
static sys_event_queue_t equeue;
|
|
static sys_event_queue_attribute_t eattr;
|
|
static sys_event_port_t terminating_port;
|
|
|
|
#define TERMINATING_PORT_NAME 0xFEE1DEAD
|
|
#define SPU_PORT_PRINTF 0x1
|
|
|
|
int spu_printf_server_initialize()
|
|
{
|
|
int ret;
|
|
|
|
/* Create event */
|
|
sys_event_queue_attribute_initialize(eattr);
|
|
ret = sys_event_queue_create(&equeue, &eattr, SYS_EVENT_PORT_LOCAL, 127);
|
|
if (ret) {
|
|
printf("sys_event_queue_create faild %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
/* Create PPU thread */
|
|
ret = sys_ppu_thread_create(&thread, spu_printf_server_entry, 0UL, PRIO,
|
|
STACK_SIZE,
|
|
SYS_PPU_THREAD_CREATE_JOINABLE,
|
|
(char*)"spu_printf_server");
|
|
if (ret) {
|
|
printf ("spu_printf_server_initialize: sys_ppu_thread_create failed %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Create the terminating port. This port is used only in
|
|
* sys_printf_server_finalize().
|
|
*/
|
|
ret = sys_event_port_create(&terminating_port,
|
|
SYS_EVENT_PORT_LOCAL,
|
|
TERMINATING_PORT_NAME);
|
|
if (ret) {
|
|
printf ("spu_printf_server_initialize: sys_event_port_create failed %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
ret = sys_event_port_connect_local(terminating_port, equeue);
|
|
if (ret) {
|
|
printf ("spu_printf_server_initialize: sys_event_port_connect_local failed %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Before call this, SPU threads which are registered finishes to send
|
|
* printf event.
|
|
*/
|
|
int spu_printf_server_finalize()
|
|
{
|
|
int ret;
|
|
|
|
/*
|
|
* Send an event from the terminating port to notify the termination to
|
|
* the SPU printf server
|
|
*/
|
|
ret = sys_event_port_send(terminating_port, 0, 0, 0);
|
|
if (ret) {
|
|
printf("sys_event_queue_cancel failed %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
/* Wait for the termination of the SPU printf server */
|
|
uint64_t exit_status;
|
|
ret = sys_ppu_thread_join(thread, &exit_status);
|
|
if (ret) {
|
|
printf("sys_ppu_thread_join failed %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
/* Disconnect and destroy the terminating port */
|
|
ret = sys_event_port_disconnect(terminating_port);
|
|
if (ret) {
|
|
printf("sys_event_disconnect failed %d\n", ret);
|
|
}
|
|
ret = sys_event_port_destroy(terminating_port);
|
|
if (ret) {
|
|
printf("sys_event_port_destroy failed %d\n", ret);
|
|
}
|
|
|
|
/* Destroy the event queue */
|
|
ret = sys_event_queue_destroy(equeue, 0);
|
|
if (ret) {
|
|
printf("sys_event_queue_destroy failed %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int spu_printf_server_register(sys_spu_thread_t spu)
|
|
{
|
|
int ret;
|
|
|
|
ret = sys_spu_thread_connect_event(spu, equeue,
|
|
SYS_SPU_THREAD_EVENT_USER, SPU_PORT_PRINTF);
|
|
if (ret) {
|
|
printf("sys_spu_thread_connect_event faild %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int spu_printf_server_unregister(sys_spu_thread_t spu)
|
|
{
|
|
int ret;
|
|
|
|
ret = sys_spu_thread_disconnect_event(spu,
|
|
SYS_SPU_THREAD_EVENT_USER, SPU_PORT_PRINTF);
|
|
if (ret) {
|
|
printf("sys_spu_thread_disconnect_event faild %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void spu_printf_server_entry(uint64_t arg)
|
|
{
|
|
(void)arg; /* This thread does not use the argument */
|
|
|
|
int ret;
|
|
sys_event_t event;
|
|
sys_spu_thread_t spu;
|
|
|
|
for (;;) {
|
|
ret = sys_event_queue_receive(equeue, &event, SYS_NO_TIMEOUT);
|
|
if (ret) {
|
|
printf("sys_event_queue_receive failed %d\n", ret);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* If an event is sent from the terminating port, the SPU printf
|
|
* server exits.
|
|
*/
|
|
if (event.source == TERMINATING_PORT_NAME) {
|
|
printf("Finalize the SPU printf server.\n");
|
|
break;
|
|
}
|
|
|
|
spu = event.data1;
|
|
|
|
int sret = spu_thread_printf(spu, event.data3);
|
|
ret = sys_spu_thread_write_spu_mb(spu, sret);
|
|
if (ret) {
|
|
printf("sys_spu_thread_write_spu_mb failed %d\n", ret);
|
|
break;
|
|
}
|
|
}
|
|
|
|
sys_ppu_thread_exit(0);
|
|
}
|
|
|