📄 bsapi.h
字号:
/* Copyright (c) 2007 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * bsapi.h - blue-steel API definitions * @author Brian Sweatt * * Contains methods that are to be exposed to the user on the PPU for initializing the ray tracing engine, * as well as setting viewing parameters, and rendering the image asynchronously to the PPU program. * * This file cannot be included in SPU programs. * The simplified user interface API is specified towards the end of the file. * The bulk of the methods at the top are used for sending messages to the SPU ray tracing program. Most * users will not need to utilize these methods directly. */#ifndef _BSAPI_H_#define _BSAPI_H_extern "C" { #include <libspe.h>}extern spe_program_handle_t spu_raytracer;typedef struct { speid_t id; spe_spu_control_area_t *control_ps_area;} spe_info_t;spe_info_t rendering_spe[TOTAL_SPES];/** * Send a render scene message to the spe specified by spe_num * Waits until all 4 in_mbox spots are open, then sends: * 1) The SPE_RENDER_REGION opcode * 2) The memory location to store the rendered scene to * 3) The starting x-coordinate of the region to render * 4) The starting y-coordinate of the region to render * It then waits for another 2 spots to open and sends: * 5) The width of the region to render * 6) The height of the region to render */inline void send_spe_render_region(int spe_num, uint32_t addr, uint32_t startx, uint32_t starty) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4){dprintf("(PPE)Waiting on (%i)\n", spe_num);} spe_write_in_mbox(rendering_spe[spe_num].id, SPE_RENDER_REGION); spe_write_in_mbox(rendering_spe[spe_num].id, addr); spe_write_in_mbox(rendering_spe[spe_num].id, startx); spe_write_in_mbox(rendering_spe[spe_num].id, starty);} /** * Sends a read scene message to the spe specified by spe_num * waits until 3 in_mbox spots are open, then sends: * 1) The SPE_READ_SCENE opcode * 2) The memory location of the start of the object array * 3) The number of objects to load from the object array */inline void send_spe_read_scene(int spe_num, uint32_t addr, uint32_t num_objs) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 3); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_READ_SCENE); spe_write_in_mbox(rendering_spe[spe_num].id, addr); spe_write_in_mbox(rendering_spe[spe_num].id, num_objs);}/** * Sends an update camera message to the spe specified by spe_num * Waits until 2 in_mbox spots are open, then sends: * 1) The SPE_UPDATE_CAMERA opcode * 2) The memory location of a CameraControl structure */inline void send_spe_update_camera(int spe_num, uint32_t cc_addr) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 2); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_UPDATE_CAMERA); spe_write_in_mbox(rendering_spe[spe_num].id, cc_addr);}/** * Sends a update camera position message to the spe specified by spe_num * Waits until all 4 in_mbox spots are open, then sends: * 1) The SPE_UPDATE_CAMERA_POS opcode * 2) The new x coordinate for the camera * 3) The new y coordinate for the camera * 4) The new z coordinate for the camera */inline void send_spe_update_camera_pos(int spe_num, float newX, float newY, float newZ) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_UPDATE_CAMERA_POS); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(newX)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(newY)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(newZ));} /** * Sends a update ball 1 position message to the spe specified by spe_num * Waits until all 4 in_mbox spots are open, then sends: * 1) The SPE_UPDATE_BALL1 opcode * 2) The new x coordinate for the ball * 3) The new y coordinate for the ball * 4) The new z coordinate for the ball */inline void send_spe_update_ball1(int spe_num, float newX, float newY, float newZ) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_UPDATE_BALL1); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(newX)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(newY)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(newZ));} /** * Sends a message to an spe to splat a region with an RGB color * Waits until 4 in_mbox spots are open, then sends: * 1) The SPE_SPLAT_REGION opcode * 2) The address of the region to be splatted * 3) The width of the region to be splatted * 4) The height of the region to be splatted * It then waits for 3 spots to open up, and sends * 5) The R value of the splat color * 6) The G value of the splat color * 7) The B value of the splat color */inline void send_spe_splat_region(int spe_num, uint32_t addr, uint32_t width, uint32_t height, float R, float G, float B) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_SPLAT_REGION); spe_write_in_mbox(rendering_spe[spe_num].id, addr); spe_write_in_mbox(rendering_spe[spe_num].id, width); spe_write_in_mbox(rendering_spe[spe_num].id, height); dprintf("(PPE)Finished first splat_region delivery to (%i)\n", spe_num); while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 3){dprintf("(PPE)Waiting on (%i)\n", spe_num);} dprintf("(PPE)Done waiting on splat spots to open on (%i)\n", spe_num); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(R)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(G)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(B));} /** * Sends a message to an spe to update the number of spheres it can havex * Waits for 2 in_mbox spots to open, then sends: * 1) The SPE_SET_NUM_SPHERES opcode * 2) The new number of spheres the spe can have */inline void send_spe_set_num_spheres(int spe_num, uint32_t num_spheres) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 2); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_SET_NUM_SPHERES); spe_write_in_mbox(rendering_spe[spe_num].id, num_spheres);}/** * Sends a message to an spe telling it to add a sphere to it's object array * Waits for 4 in_mbox spots to open, then sends: * 1) The SPE_ADD_SPHERE opcode * 2, 3, 4) The x, y, and z coordinates for the sphere * It then waits for 2 in_mbox spots to open up, and sends: * 5) The radius of the sphere * 6) The material id of the sphere */inline void send_spe_add_sphere(int spe_num, float x, float y, float z, float r, uint32_t m_id) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_ADD_SPHERE); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(x)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(y)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(z)); while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 2); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(r)); spe_write_in_mbox(rendering_spe[spe_num].id, m_id);}inline void send_spe_set_num_triangles(int spe_num, uint32_t num_triangles) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 2); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_SET_NUM_TRIANGLES); spe_write_in_mbox(rendering_spe[spe_num].id, num_triangles);}inline void send_spe_add_triangle(int spe_num, float ax, float ay, float az, float bx, float by, float bz, float cx, float cy, float cz, uint32_t m_id) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_ADD_TRIANGLE); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(ax)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(ay)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(az)); while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 3); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(bx)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(by)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(bz)); while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(cx)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(cy)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(cz)); spe_write_in_mbox(rendering_spe[spe_num].id, m_id);}inline void send_spe_set_num_spes(int spe_num, uint32_t stride) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 2); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_SET_NUM_SPES); spe_write_in_mbox(rendering_spe[spe_num].id, stride);}/** * Sends the address of an ObjectSet object containing pointers to the objects in the scene * Waits until two mailbox slots open up, then sends: * 1) The SPE_GET_OBJECTSET opcode * 2) The address of the ObjectSet to DMA from main memory (as a uint32_t) */inline void send_spe_init_raytracer(int spe_num, ObjectSet *objects) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 2); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_INIT_RAYTRACER); spe_write_in_mbox(rendering_spe[spe_num].id, (uint32_t) objects);}inline void send_spe_set_ambient(int spe_num, float r, float g, float b) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_SET_AMBIENT); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(r)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(g)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(b));}inline void send_spe_look_at(int spe_num, float x, float y, float z, float ux, float uy, float uz) { while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, SPE_LOOK_AT); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(x)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(y)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(z)); while (spe_stat_in_mbox(rendering_spe[spe_num].id) < 4); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(ux)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(uy)); spe_write_in_mbox(rendering_spe[spe_num].id, float_as_uint32(uz));}//////////////////////////////////////////////////////// Simplified user interface methods for blue-steel /////////////////////////////////////////////////////////** * Called to initialize the SPU ray tracer with the current number of SPUs defined in common.h * As well as the ObjectSet being passed in to represent the scene to be rendered * Subsequent calls to bsRenderScene will use this ObjectSet to render the scene * @param objects A pointer to the ObjectSet representing the scene to be rendered */inline void bsInit(ObjectSet *objects) { for (int i = 0; i < NUM_RENDERING_SPES; i++) { rendering_spe[i].id = spe_create_thread(0, &spu_raytracer, (void *)i, NULL, -1, 0); } for (int i = 0; i < NUM_RENDERING_SPES; i++) { send_spe_init_raytracer(i, objects); send_spe_set_num_spes(i, NUM_RENDERING_SPES); }}/** * Tells the SPU raytracer to start the asynchronous rendering process for the current scene * Please note: The image buffer being passed in must have the dimensions specified in common.h * @param image An array of vector unsigned ints that will hold the image data for the rendered scene */inline void bsRenderScene(vector unsigned int *image) { for (int i = 0; i < NUM_RENDERING_SPES; i++) { send_spe_render_region(i,(uint32_t) &image[STRIP_WIDTH*i], 0, i); }}/** * Given a point in space to look at, as well as direction that will be considered as 'up' * This method sets the Camera in the ray tracer to look at the given point. * @param x The x-coordinate of the point for the camera to look at * @param y The y-coordinate of the point for the camera to look at * @param z The z-coordinate of the point for the camera to look at * @param ux The component of the up direction in the unit x direction * @param ux The component of the up direction in the unit y direction * @param ux The component of the up direction in the unit z direction */inline void bsLookAt(float x, float y, float z, float ux, float uy, float uz) { for (int i = 0; i < NUM_RENDERING_SPES; i++) { send_spe_look_at(i, x, y, z, ux, uy, uz); }}/** * Sets the position of the center of the camera, to be applied to the next frame rendered. * @param x The x-coordinate of the new center of the camera * @param y The y-coordinate of the new center of the camera * @param z The z-coordinate of the new center of the camera */ inline void bsSetCenter(float x, float y, float z) { for (int i = 0; i < NUM_RENDERING_SPES; i++) { send_spe_update_camera_pos(i, x, y, z); }}/** * Sets the ambient lighting to be used in the rendered image * This is a faked constant ambient illumination * @param r The red component of the ambient lighting to be applied * @param g The green component of the ambient lighting to be applied * @param b The blue component of the ambient lighting to be applied */inline void bsAmbient(float r, float g, float b) { for (int i = 0; i < NUM_RENDERING_SPES; i++) { send_spe_set_ambient(i, r, g, b); }}/** * Waits for the current rendering to finish. Upon return, the image buffer passed in * to bsRenderScene will be filled with the completed rendering of the scene */inline void bsWait() { for (int i = 0; i < NUM_RENDERING_SPES; i++) { while (spe_stat_out_mbox(rendering_spe[i].id) == 0); spe_read_out_mbox(rendering_spe[i].id); }}/** * Checks whether the last rendering operation has completed. * This method returns true if it has, false otherwise */inline bool bsDone() { for (int i = 0; i < NUM_RENDERING_SPES; i++) { if (spe_stat_out_mbox(rendering_spe[i].id) == 0) return false; } return true;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -