The default RpAtomic, RpWorldSector and RpMaterial pipelines provided for PlayStation2 are implemented using the PS2All, PS2All and PS2AllMat nodes respectively. Each pipeline contains just a single node on the EE core and dispatches to microcode running on VU1. To support customization of these pipelines, the PS2All and PS2AllMat nodes have many API functions and expose several overloadable callback functions. An application can use these callbacks to arrange for application code to be called during the pipeline execution. (This technique is therefore functionally equivalent to a series of nodes.) For details, refer to the user guide chapter 'PS2All Overview' and the API reference documentation for RxNodeDefinitionGetPS2All and RxNodeDefinitionGetPS2AllMat.
|
RxPipelineNodePS2AllMatBridgeCallBack is the callback to be called, for the owning PS2All.csl pipeline node, before the mesh's instance data is dispatched to VU1 for rendering. This callback should be used to upload various pieces of information to VU1, including (finally) the mesh's instance data. This involves constructing a DMA packet, which is quite involved - so there are several macros provided to construct this packet for you. In summary, you should call RpMeshPS2AllAsyncTextureUpload and then RpMeshPS2AllSyncTextureUpload to upload your texture first of all. Then, you should open the VU1 uploads (VIF) packet with RpMeshPS2AllStartVIFUploads, perform several uploads (individual macros are listed below) and finally call RpMeshPS2AllEndVIFUploads to initiate dispatch of your mesh's instance data to VU1. These last two are the only obligatory function calls which you must make in your RxPipelineNodePS2AllMatBridgeCallBack (if they are omitted then there won't be a crash, but nothing will be rendered since the mesh instance data will not be dispatched to VU1), all others are optional (in general, if they are omitted then prior state will persist). RpMeshPS2AllStartVIFUploads opens a VIF packet and the following macros will add small uploads to this packet:
See the documentation for RpMeshPS2AllStartVIFUploads for details on how to perform further VIF uploads (beyond the default ones provided for by the macros listed above) in your RxPipelineNodePS2AllMatBridgeCallBack. Note that the macros listed above will be functions in a debug build. You may explicity select a function or macro version (depending on how you want to balance code size and function call overheads) by appending 'Func' or 'Macro' to the end of the name. For example, to select the function version of RpMeshPS2AllMatColUpload, you would call 'RpMeshPS2AllMatColUploadFunc'. The macros use several values in the RxPS2AllPipeData struct. These all have valid defaults, which may be overridden. The default values of RxPS2AllPipeData members used in the macros are: vu1CodeIndex = ps2AllPipeData.transType & (rxSKYTRANSTYPEFOG | rxSKYTRANSTYPECLIP | rxSKYTRANSTYPELIST | rxSKYTRANSTYPEISO | rxSKYTRANSTYPELINE), texture = mesh->material->texture, surfProps = &(material->surfaceProps), matCol = (ps2AllPipeData->matModulate) ? mesh->material->color : {255, 255, 255, 255} The default RenderWare RxPipelineNodePS2AllMatBridgeCallBack function for RpAtomics and RpWorldSectors is RpMeshPS2AllBridgeCallBack and for RwIm3D is RwIm3DPS2AllBridgeCallBack. The documentation for these defaults list the macros from which they are constructed so that you may construct replacement callbacks with your own modifications. This callback is required for PS2AllMat.csl to function. If it is set to NULL (it is initialized to NULL when the pipeline is unlocked), then there will be an ASSERT (in debug) and a crash.
|
|
RxPipelineNodePS2AllMatInstanceCallBack is the callback to be called, for the owning PS2All.csl pipeline node, to instance a mesh. The instance callback will receive an array of pointers to cluster data for all 'visible' clusters - those that have CL_ATTRIB_READ or CL_ATTRIB_WRITE specified in their attributes (these are the clusters that can be filled in by user CPU-side code). The order of the clusters in the array will be the order in which they appear in the RxPS2ClusterType enumeration type (this does indeed imply that no cluster may be requested twice - see RxPipelineNodePS2AllMatGenerateCluster for further details). Even if there are no 'visible' clusters, the callback will still be called, because non-visible, standard clusters may need instancing. Functions are available (for use in this callback) to instance the standard cluster types for you (for RpAtomics, RpWorldSectors and RwIm3D), so that you only have to instance user clusters. These are: RpAtomicPS2AllInstance, RpWorldSectorPS2AllInstance, RwIm3DPS2AllInstance Visible clusters will be 'broken out' from the usual (complex, packed) format of DMA packet data such that their data is accessible as a simple, contiguous array. A cluster specified as CL_ATTRIB_READ or CL_ATTRIB_WRITE will be visible and this callback will receive a pointer to its data when instancing occurs. Clusters flagged with CL_ATTRIB_DONT_FILL or CL_ATTRIB_PLACEHOLDER will be skipped by these default instance functions and you will have to instance data for the former yourself. Clusters marked as CL_ATTRIB_PLACEHOLDER don't need instance data (see RxPS2ClusterAttrib for details of cluster attribute flags). The default instancing functions can instance from meshes containing any RwPrimitiveType, indexed or unindexed. User-supplied callbacks, however, need only handle meshes of the types used by the user. Note also that the default RenderWare atomic instance function sets up three members of the rwPS2AllResEntryHeader at the top of instance data, so that these can be used in reinstance tests (morphing is such that instancing must occur when the morph targets in use change). It sets morphStart (the start morph target), morphFinish (the end morph target) and morphNum (the number of morph targets in the object). These are initialized, outside this function, to zero, zero and one, respectively, by default. If clusters flagged with CL_ATTRIB_DONT_FILL are not flagged with CL_ATTRIB_READ or CL_ATTRIB_WRITE then you will not receive a pointer to their data because it will be in the opaque internal format. It is possible (and there are DMA transfer efficiency benefits. Note that opaque user clusters are not currently supported) to instance into this format but it is complicated and not not recommended without assistance. For the brave of heart, here is a brief description of how to traverse opaque instance data: First, access the strip or list members of the PS2AllMat.csl node's private data (list should be used for tri-lists, line-lists and point-lists and strip for tri-strips and poly-lines - note that triFans are not supported on VU1 and are instanced into tri-lists). batchSize gives the number of vertices per batch, where this is equal to the number of indices (we 'dereference' indices when instancing, we only deal with vertices on VU1). Note that for tri-strips, the first two vertices of a batch MUST be the same as the last two vertices of the previous batch, so that strips can continue across batches - similarly for poly-lines but with just one vertex). The fieldRec array facilitates instance data traversal for each cluster (order given by RxPS2ClusterType). Within this, numVerts is batchSize again (it is different for non-opaque clusters), dataoffset is the offset from the start of the instance data (in QuadWords) to the start of the first batch of data for this cluster (instance data is pointed to by the data member of the rwPS2AllResEntryHeader at the head of instance data - get it using RWPS2ALLRESENTRYHEADERFROMRESENTRY). Skip is the (QuadWord) offset from the beginning of a cluster's data in one batch to the next. Reverse is a negative (QuadWord) offset used for the last batch (in which the data of all the clusters may be smaller, so they need to be shuffled back to pack together). DMA and VIF tags are placed in-between batches of cluster data, so be careful not to overrun! Members beginning with 'morph' are to be used for morphing objects (those which have more than one morphTarget and currently have differing start and end targets). Internally, a second XYZ cluster is created, if XYZs are present, in slot CL_MAXCL. This is for the 'end' morph target. If NORMALs are present, (CL_MAXCL+1) will be used for a second version of those. If you are doing the instancing for XYZs or NORMALs then you will also have to (for morphing objects) do the instancing for the second set of each. The default RxPipelineNodePS2AllMatInstanceCallBack for RpAtomics and RpWorldSectors is RpMeshPS2AllInstanceCallBack. For RwIm3D, the default is RwIm3DPS2AllInstanceCallBack. The documentation for these defaults list the macros and sub-functions from which they are constructed so that you may (partially or fully) reconstruct them and make your own modifications. This callback is not required for PS2AllMat.csl to function. It may safely be set to NULL (it is initialized to NULL when the pipeline is unlocked).
|
|
RxPipelineNodePS2AllMatMeshInstanceTestCallBack is the callback to be called, for the owning PS2All.csl pipeline node, to decide whether a mesh should be reinstanced or not. To control mesh instancing, set up meshInstance and meshIdentifier. meshIdentifier is a value stored in the rwPS2AllResEntryHeader structure which heads up instance data and which can be inspected to determine if a mesh has changed sufficiently, since it was last instanced, to merit its being reinstanced. How you construct this value is up to you. The default RenderWare callback (used by the default RpAtomic and RpWorldSector pipelines - in RwIm3D there's no need for testing since we are instancing from scratch every time we render), RpMeshPS2AllMeshInstanceTestCallBack uses the mesh header's flags. objInstance is of type RxInstanceFlags and an overview of its use is given here: RxPipelineNodePS2AllSetCallBack. In order to retrieve the value meshIdentifier from the instance data, dereference the meshCache member and extract the rwPS2AllResEntryHeader with the macro RWPS2ALLRESENTRYHEADERFROMRESENTRY. As detailed in the documentation for the RxInstanceFlags, you may specify that a mesh should be reinstanced in-place, congruently, fully or not at all. The meshInstance member will be initialized to the value of the objInstance member (ORed with rxINSTANCEDONTINSTANCE to assure sensible default behavior), so if this callback is set to NULL (it is initialized to NULL when the pipeline is unlocked), the decision made by the RxPipelineNodePS2AllObjectSetupCallBack will be used. Even if present, this callback will only be called if objInstance isn't set to rxINSTANCEDONTINSTANCE (see the overview of instance testing in the documentation for RxPipelineNodePS2AllSetCallBack). The number of vertices in the instance data of a mesh (a vertex being a dereferenced index) should also cause a full reinstance if it changes. numVerts is stored in the rwPS2AllResEntryHeader and may be calculated using the macro RPMESHPS2ALLCALCNUMVERTS. The default RxPipelineNodePS2AllMatMeshInstanceTestCallBack for RpAtomics and RpWorldSectors is RpMeshPS2AllMeshInstanceTestCallBack. RwIm3D uses no such callback, since in its case instancing starts from scratch every render. The documentation for RpMeshPS2AllMeshInstanceTestCallBack list the macros from which it is constructed so that you may (partially or fully) reconstruct it and make your own modifications. In summary, the things this callback can (optionally) set up are: meshIdentifier, meshInstance The default values of these things are: meshIdentifier = 0, meshInstance = (objInstance | rxINSTANCEDONTINSTANCE)
|
|
RxPipelineNodePS2AllMatPostMeshCallBack is the callback to be called, for the owning PS2All.csl pipeline node, after the mesh's instance data is dispatched to VU1 for rendering. This callback may be used to perform tasks necessary after the rendering of a mesh. The default RenderWare callback, RpMeshPS2AllPostMeshCallBack, accumulates metrics information, so replacement callbacks must do so also if metrics information is to be accurate. The documentation for this default callback list the macros from which it is constructed so that you may (partially or fully) reconstruct the default callback and make your own modifications. This callback is not required for PS2All.csl to function. It may be set to NULL (it is initialized to NULL when the pipeline is unlocked).
|
|
RxPipelineNodePS2AllMatResEntryAllocCallBack is the callback to be called, for the owning PS2All.csl pipeline node, to allocate memory for a mesh's instance data. If the callback allocates memory with RwResourcesAllocateResEntry then the destroyNotify parameter must be passed to it (in addition to the doubly-indirected RwResEntry pointer). The purpose of destroyNotify is to ensure that all DMA transfers involving the allocated block of memory have been completed before the memory is freed. If you allocate your own memory (note that it must be headed up by a RwResEntry structure, with 'size' bytes after that) then you should use this callback in your free function to ensure the same (if this is unfeasible, the mechanism is to loop until the refCnt member of the rwPS2AllResEntryHeader in the instance data becomes zero. To access this, dereference the meshCache member and extract the rwPS2AllResEntryHeader with the macro RWPS2ALLRESENTRYHEADERFROMRESENTRY). The default RxPipelineNodePS2AllMatResEntryAllocCallBack for RpAtomics and RpWorldSectors is RpMeshPS2AllResEntryAllocCallBack. For RwIm3D, the default is RwIm3DPS2AllResEntryAllocCallBack. The documentation for these defaults list the macros from which they are constructed so that you may (partially or fully) reconstruct them and make your own modifications. This callback is required for PS2AllMat.csl to function. If it is set to NULL (it is initialized to NULL when the pipeline is unlocked), then there will be an ASSERT (in debug) and a crash if any instancing occurs (this may not happen in one particular circumstance - if you are using 'persistent instance data' - a new and currently unsupported feature accessible through _rpGeometryInstance, which instances an RpGeometry into memory outside of the resource arena so that it can be streamed to and read from disk and need never be instanced again).
|
|
RxPipelineNodePS2AllObjectFinalizeCallBack is the callback to be called, for the owning PS2All.csl pipeline node, once all meshes in the object have been rendered. This callback can be used to perform tasks necessary after the rendering of all meshes in the object. No RenderWare objects currently use a callback of this type in their default pipelines, though it has been used in the past and is included because it may still prove to be of use to developers. This callback is not required for PS2All.csl to function. It may safely be set to NULL (it is initialized to NULL when the pipeline is unlocked).
|
|
RxPipelineNodePS2AllObjectSetupCallBack is the callback to be called, for the owning PS2All.csl pipeline node, to perform per-object setup tasks prior to rendering. Since it is the first callback called and since the objects being rendered are arbitrary (they need not be RpAtomics or RpWorldSectors but they must contain RpMeshHeaders and RpMeshes), this callback needs to initialize several fields of the RxPS2AllPipeData structure with information about the object, as follows: Firstly, the callback needs to extract a pointer to the RpMeshHeader in the object and put it in the meshHeader field. [strictly speaking, this is only necessary if per-mesh instance tests or instancing are going to occur] Secondly, the meshCache field needs to be filled. You can extract a pointer to the RwMeshCache in atomics, geometries and world sectors using rpGeometryGetMeshCache, rpAtomicGetMeshCache and rpWorldSectorGetMeshCache respectively. Note that if your geometry has more than one morphtarget then the meshcache will hang off the atomic instead of the geometry (different atomics may be in different animation states, so the instance data can't be shared). If the object has multiple RpMorphTargets and is to be morph animated then the numMorphTargets field should be set up as appropriate. Also, the current 'scale' value (0-1, the linear interpolant between the current start and end morphtargets) needs to be uploaded. Set the spExtra field to this value so that it will be uploaded in a spare slot in the quadword containing surface properties. Calculate the value thus: "interpolator->recipTime*interpolator->position". To control mesh instancing, set up objInstance and objIdentifier. objIdentifier is a value stored in the rwPS2AllResEntryHeader structure which heads up instance data and which can be inspected to determine if an object has changed sufficiently, since its meshes were last instanced, to merit their being reinstanced. How you construct this value is up to you. The default RenderWare callbacks use a combination of the mesh header's serial number, object flags and the object's number of morph targets. objInstance is an RxInstanceFlags value and an overview of its use is given here: RxPipelineNodePS2AllSetCallBack. To retrieve objIdentifier from the instance data, dereference the meshCache member and extract the rwPS2AllResEntryHeader with the macro RWPS2ALLRESENTRYHEADERFROMRESENTRY. As detailed in the documentation for the RxInstanceFlags, you may specify that an object's meshes should be reinstanced in-place, congruently, fully or not at all. For the default RxPipelineNodePS2AllObjectSetupCallBack for RpAtomics, RpAtomicPS2AllObjectSetupCallBack, a macro is called (RpAtomicPS2AllClear) to clear flags in the contained RpGeometry relating to reinstancing, once the instance tests have been performed. The primType field should to be initialized to the GS primitive type which will be submitted by your vector code. This value will get uploaded in a GIFTag placed in the VU1 static memory area - this can be ignored by your vector code if you so wish. primType may be set up in an RxPipelineNodePS2AllMatBridgeCallBack instead of here if that is so desired (this could feasibly be useful if, say, frustum-testing is being performed on a per-mesh basis). As of this writing, GS primitive type values are listed on p113 of the GS manual, in section 7.1 The transtype field should be initialized to specify the type of the VU1 transform code which will be used. This field is a bitfield constructed from RxSkyTransTypeFlags. It will be used by material pipelines to select the appropriate VU1 code fragment from the VU1 code array. For an example, code which clips triangles is generally much slower than code which does not, so you could perform a camera frustum intersection test on a bounding volume of your object to decide whether to set the rxSKYTRANSTYPECLIP flag. The default RenderWare code for RpAtomics and RpWorldSectors does this. Im3D relies on a hint flag passed to RwIm3DTransform. The matModulate field specifies whether the material colors of the object should be modulated with lighting values. Simply set it to TRUE or FALSE. Setting it to FALSE is equivalent to giving all your materials the color {255, 255, 255, 255}. The object-space to camera-space transformation matrix may be set up (though the transform parameter). To do this, concatenate the object's LTM matrix with the current camera's view matrix. Alternatively, if you have calculated or cached a complete transform matrix elsewhere, you may simply change the transform pointer (hence the double indirection). If you wish for the matrix currently in VU1 memory to persist, you may set the pointer to the matrix to be NULL (the transform parameter is doubly indirected). This is a useful performance win for geometry which is specified in world-space or camera-space. In order for dynamic lighting to work, the object setup callback should evaluate which lights affect the current object and for each such light call RxPipelineNodePS2AllApplyLight (which is of type RxWorldApplyLightFunc), passing a pointer to the light, the inverse LTM of the object, the matrix's scaling factor and its reciprocal (these are both 1.0 unless the matrix is non-normalized Only orthogonal matrices are allowed). The latter two parameters are actually only required for the first light passed. Here is the prototype of the RxWorldApplyLightFunc callback: void (*RxWorldApplyLightFunc)(const void *voidLight, const RwMatrix *inverseMat, RwReal invScale, RwReal recipInvScale); The default lighting code used for atomics is contained in RpAtomicPS2AllLightingSetup. For sectors, RpWorldSectorPS2AllLightingSetup is used. These use the helper functions: RxPipelineNodePS2AllApplyLight, RpAtomicForAllWorldSectors, rpWorldSectorForAllLocalLights, rpWorldForAllGlobalLights, RpAtomicPS2AllDoApplyLight, RpAtomicPS2AllDoApplyLightFrame and RpWorldSectorPS2AllDoApplyLight. You may in some cases use RpAtomicPS2AllLightingPersist in a user callback, as an optimisation for either RpAtomics or RpWorldSectors. Lights are by default not used for Im3D (though on PlayStation 2 they may be - the same VU1 code is used as for atomics and world sectors). If no lighting setup is done then no lights will be uploaded to VU1. To compensate, your vector code could contain hard-coded lights or you could upload lights into static data in the RxPipelineNodePS2AllMatInstanceCallBack. Note that the default RenderWare callbacks accumulate metrics information, so replacement callbacks must do so also if metrics information is to be accurate. You may use these helper functions to gather metrics information: The default RxPipelineNodePS2AllObjectSetupCallBack for RpAtomics is RpAtomicPS2AllObjectSetupCallBack. For RpWorldSectors, the default is RpWorldSectorPS2AllObjectSetupCallBack and for RwIm3D the default is RwIm3DPS2AllObjectSetupCallBack. The documentation for these default callbacks list the macros from which they are constructed so that you may (partially or fully) reconstruct the default callbacks and make your own modifications. Note that the macros contain RWASSERT, so they must be used within functions using RWFUNCTION and RWRETURN. In summary, the things this callback MUST set up are: meshHeader, meshCache The default values of RxPS2AllPipeData members are: transform = UNDEFINED, (or persistent) meshHeader = NULL, meshCache = NULL, numMorphTargets = 1, spExtra = 0, objInstance = 0, objIdentifier = 0, primType = UNDEFINED, transType = NoFog|NoClip|Strip|Persp|Tri|NoCull, matModulate = FALSE The callback can prematurely terminate pipeline execution by returning FALSE. This callback is required for PS2All.csl to function. If it is set to NULL (it is initialized to NULL when the pipeline is unlocked), then there will be an ASSERT (in debug) and a crash.
|
|
RxWorldLightingCallBack RxWorldLightingCallBack is a call back function for lighting.
|
|
RxInstanceFlags These flags control the decision of whether to re-instance meshes during the execution of PS2All.csl and PS2AllMat.csl. See RxPipelineNodePS2AllSetCallBack for an overview of this process.
|
|
RxPipelineNodePS2AllCallBackType PS2All.csl callback types (see RxPipelineNodePS2AllSetCallBack and RxPipelineNodePS2AllMatSetCallBack), in order of execution within the node.
|
|
RxPipelineNodePS2AllMatCallBackType PS2AllMat.csl callback types (see RxPipelineNodePS2AllMatSetCallBack and RxPipelineNodePS2AllSetCallBack), in order of execution within the node.
|
|
|
Flags in PlayStation 2-specific cluster attributes defining the format of cluster data in DMA packets. These formats get expanded by the VIF on upload to VU1.
|
|
Values specifying the type of PlayStation 2-specific clusters. See RxPipelineNodePS2AllMatGenerateCluster. There are only ten possible clusters uploadable to VU1 on PlayStation 2 currently. The generic clusters are always uploaded to VU1 in the order listed VU (some can be missing) and the user data clusters come after that. The data format of the four standard clusters is fixed, changing the attributes value for that won't work
|
|
RxPS2ObjectType Values identifying different PlayStation 2-specific object types.
|
|
RxSkyTransTypeFlags Flags specifying the desired behavior for the current VU1 transform.
|
|
RxNodeDefinitionGetPS2All returns a pointer to the "PS2All.csl", node definition, which is used to render RenderWare (or custom) objects. This node does everything required to render an object. This node will not pass packets on to subsequent nodes in the pipeline nor will accept them from previous nodes. It was designed to be the only node in a pipeline, for maximum speed. [Note that the PVSData.csl node, if placed before PS2All.csl in a pipeline, will still work since it doesn't use packets and merely terminates the pipeline prematurely dependent on PVS data.] This node will take into account pipelines specified in materials within an object. Such pipelines must be constructed from the PS2AllMat.csl node only (see RxNodeDefinitionGetPS2AllMat). Using other nodes will simply cause RenderWare to ASSERT and crash. On the PlayStation 2, instancing of data is performed in the material pipeline on a per-mesh basis. This is because different material pipelines can require data to be instanced into a different format, depending on what the VU1 code (associated with the pipeline) requires. PS2All.csl is thus not equivalent to AtomicInstance.csl or WorldSectorInstance.csl which form the default generic atomic and world sector object pipelines. Instead, it does per-object setup and then allows material pipelines to do instancing and other work per-mesh. After object setup and instancing, mesh material properties (such as texture) are uploaded to VU1 and the geometry is added to the DMA transfer queue (the DMA engine may run several frames behind the CPU). This node is customisable by the setting of callback functions. See RxPipelineNodePS2AllSetCallBack and RxPipelineNodePS2AllMatSetCallBack for details (the former also contains an overview of the flow of pipeline execution through PS2All.csl and PS2AllMat.csl). Because of this, PS2All.csl and PS2AllMat.csl should be the only nodes you need to use on PlayStation 2, the former for object pipelines and the latter for material pipelines. NOTE: When using PS2All.csl to construct an Im3D render pipeline, you MUST use RxPipelineNodePS2AllGroupMeshes to point to the material pipeline which will be used - this is because there are no materials in Im3D with which to locate material pipelines! The Im3D transform pipeline is different altogether and it is not recommended to try replacing it without assistance.
|
|
RxNodeDefinitionGetPS2AllMat returns a pointer to the "PS2AllMat.csl", node definition, which is used to render meshes within RenderWare (or custom) objects. This node is used to construct material pipelines which will be called from PS2All.csl (from which object pipelines can be constructed), for each mesh in an object. Each mesh's material may point to a different pipeline, containing a different version of PS2AllMat.csl (set up differently by the pipeline construction-time API). This node is customisable by the setting of callback functions. See RxPipelineNodePS2AllMatSetCallBack and RxPipelineNodePS2AllSetCallBack for details (the latter also contains an overview of the flow of pipeline execution through PS2All.csl and PS2AllMat.csl). Because of this, PS2All.csl and PS2AllMat.csl should be the only nodes you need to use on PlayStation 2 (prior nodes remain for legacy support), the former for object pipelines and the latter for material pipelines. Also, note that the PS2AllMat.csl node must be the ONLY node in the material pipeline which contains it (due to the way PS2All.csl accesses this pipeline). NOTE: When using PS2All.csl and PS2AllMat.csl to construct an Im3D render pipeline, you MUST use RxPipelineNodePS2AllGroupMeshes to point to the material pipeline which will be used - this is because there are no materials in Im3D with which to locate material pipelines! The Im3D transform pipeline is different altogether and it is not recommended to try replacing it without assistance.
|
|
RxPipelineNodePS2AllApplyLight is the default RxWorldApplyLightFunc which may be called, for each light affecting an object, to get lighting information uploaded to VU1 by a PS2All-based object pipeline. Lighting is performed in object-space (to avoid transforming object normals), hence this function requires a matrix to transform lights from world-space into object-space (i.e. it should be the inverse of the object's LTM matrix). This matrix must be orthogonal, though it need not be normalized. Both the scaling factor (1.0 if the matrix IS normalized) and its reciprocal need to be passed to this function so that the light's radius and direction vector may be scaled and renormalized after transform. Note that the matrix and scaling values need only be supplied for the first light affecting an object - they are only uploaded once.
|
|
RxPipelineNodePS2AllGroupMeshes is a post construction time node API function used to cause a PS2All.csl node to process all meshes in an object with the same material pipeline. The default behavior of the PS2All.csl node is to process each mesh in an object with the material pipeline specified in the mesh's RpMaterial. This function overrides that behavior, by setting a material pipeline which will be used for *all* meshes in an object regardless of the value of materials in the object - it groups the meshes together and treats them all in the same way. This may be useful for efficiency or convenience. If NULL is passed to this function then the default PS2All.csl behavior is restored and the node will no longer 'group meshes'. This function should be called after unlocking the pipeline containing this node.
|
|
RxPipelineNodePS2AllMatGenerateCluster is a pre construction time node API function used to cause a PS2AllMat.csl node to generate clusters. It should be called for each of the RxClPS2* clusters required. These are the PlayStation 2-specific clusters you can request for this node (see also RxPS2ClusterType):
The format attribute flags of the first four of the above PlayStation 2-specific clusters are fixed and you cannot change them, however the other attribute flags may be changed. The user-defined clusters can have any attributes you please. Since these cluster definitions are static globals and provided really as examples, it is suggested that you create copies, modify their attributes as appropriate and submit these copies to this function. See RxClusterSetAttributes for details on changing cluster attributes. Note that in the case of PS2All.csl and PS2AllMat.csl, each cluster generated does not actually imply the presence of an RxCluster. Clusters are only present from the point of view of the instance data which is created and uploaded to VU1 by the pipeline. Cluster data may be accessed within an RxPipelineNodePS2AllMatInstanceCallBack and the details of how cluster flags affect the format of this data are given in the docs for that callback type. You have to have at least one cluster and can have a maximum of eight (one each of the RxClPS2* clusters listed above). Clusters currently have a maximum stride of one quadword though this limitation will be removed in the future. This function must be called before unlocking the pipeline containing this PS2AllMat.csl node because cluster attributes are finalized when the pipeline is unlocked.
|
|
RxPipelineNodePS2AllMatGetVU1CodeArray is a post construction time node API function which retrieves an array of pointers to the VU1 code fragments currently to be used by this pipeline. It mirrors RxPipelineNodePS2AllMatSetVU1CodeArray This function must be called after unlocking the pipeline containing the PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllMatGetVUBatchSize is a post construction time node API function used to query the batch size used for uploading data to VU1. This function mirrors RxPipelineNodePS2AllMatSetTriangleVUBufferSizes, RxPipelineNodePS2AllMatSetLineVUBufferSizes, or RxPipelineNodePS2AllMatSetPointListVUBufferSize, depending on the type of primitive being rendered by the pipeline containing this node. The return value is in vertices, so "6" would mean two triangles per batch for a trilist, four triangles for a tristrip, 3 lines for a linelist, 5 lines for a polyline or six points for a pointlist. Note that, for tristrips and polylines, the last two and one (respectively) vertices in a batch will be duplicated in the following batch, so that the tristrip/polyline can be continued. This function must be called after unlocking the pipeline containing the PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllMatSetCallBack is is a post construction time API function used to register a callback with a PS2AllMat.csl pipeline node. During its execution, the PS2AllMat.csl node (called from the PS2All.csl node) calls several callback functions. Callbacks are also called from the PS2All.csl node in object pipelines (see RxPipelineNodePS2AllSetCallBack for details). Here is a list of the callback types (in order of execution within PS2AllMat.csl) used by PS2AllMat.csl:
This function must be called before unlocking the pipeline containing this PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllMatSetLineVUBufferSizes is a pre construction time node API function which is used to set the maximum number of lines (for line-lists) and vertices (for polylines) that may be uploaded by this pipeline to VU1 in a single batch. The stride (in quad words) of the input buffer vertex in VU1 memory is also set by this function. For rwPRIMTYPELINELIST-based or rwPRIMTYPEPOLYLINE-based objects, this function should be called instead of RxPipelineNodePS2AllMatSetTriangleVUBufferSizes. They should not both be called. Pipelines set up with this function will only be able to handle line-based objects, not triangle- or point-based objects. For pipelines feeding user-supplied VU1 code, the values to pass to this function may be obtained from the pipeline-specific header file created by processing stddata.i. Note that the buffer sizes submitted may be rounded down. For line-lists, buffer sizes will be rounded to a multiple of two lines (four vertices) due to DMA read alignment requirements. For poly-lines, if your vertices contain any broken-out clusters (that is, clusters whose attributes flags contain CL_ATTRIB_READ or CL_ATTRIB_WRITE), then the buffer size will be rounded down to (4n + 1) vertices and if there are no broken-out clusters then it will be rounded down to (4n). This is due again to DMA read alignment requirements and also internal vertex duplication used to continue poly-lines between batches. If this function is not called (and neither of RxPipelineNodePS2AllMatSetTriangleVUBufferSizes and RxPipelineNodePS2AllMatSetPointListVUBufferSize are, either), then the pipeline will default to handling triangles. The input vertex stride will default to 4 quadwords and vuTSVertexMaxCount and vuTLTriangleMaxCount will default to the maximum possible batch sizes for that stride (if you have changed the VIFOffset from the default value then this will not be valid). This function must be called before unlocking the pipeline containing this PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllMatSetPointListVUBufferSize is a pre construction time node API function which is used to set the maximum number of vertices for pointlists that may be uploaded, by this pipeline, to VU1 in a single batch. The stride (in quad words) of the input buffer vertex in VU1 memory is also set by this function. For rwPRIMTYPEPOINTLIST-based objects, this function should be called instead of RxPipelineNodePS2AllMatSetTriangleVUBufferSizes. They should not both be called. Pipelines set up with this function will only be able to handle pointlist-based objects, not triangle- or line-based objects. For pipelines feeding user-supplied VU1 code, the values to pass to this function may be obtained from the pipeline-specific header file created by processing stddata.i. Note that, for a pointlist pipeline, the first half of the VU1 code array should be used - i.e the TRANSTRI slots are reused (see RxPipelineNodePS2AllMatGetVU1CodeArray and RxSkyTransTypeFlags). Note that the buffer size submitted may be rounded down. For pointlists, it will be rounded down to (4n) due to DMA read alignment requirements. If this function is not called (and neither of RxPipelineNodePS2AllMatSetLineVUBufferSizes and RxPipelineNodePS2AllMatSetTriangleVUBufferSizes are, either), then the pipeline will default to handling triangles. The input vertex stride will default to 4 quadwords and vuTSVertexMaxCount and vuTLTriangleMaxCount will default to the maximum possible batch sizes for that stride (if you have changed the VIFOffset from the default value then this will not be valid). This function must be called before unlocking the pipeline containing this PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllMatSetTriangleVUBufferSizes is a pre contruction time node API function which is used to set the maximum number of triangles (for trilists) and vertices (for tristrips) that may be uploaded, by this pipeline, to VU1 in a single batch. The stride (in quad words) of the input buffer vertex in VU1 memory is also set by this function. If this function is not called, the defaults required by the standard transforms will be used. For pipelines feeding user-supplied VU1 code, the values to pass to this function may be obtained from the pipeline-specific header file created by processing stddata.i Note that the buffer sizes submitted may be rounded down. For trilists, buffer sizes will be rounded to a multiple of four triangles (or twelve vertices) due to DMA read alignment requirements. For tristrips, if your vertices contain any broken-out clusters (that is clusters whose attributes flags contain CL_ATTRIB_READ or CL_ATTRIB_WRITE), then the buffer size will be rounded down to (4n + 2) vertices and if there are no broken-out clusters then it will be rounded down to (4n). This is due again to DMA read alignment requirements and also internal vertex duplication used to continue tristrips between batches. If this function is not called (and neither of RxPipelineNodePS2AllMatSetLineVUBufferSizes and RxPipelineNodePS2AllMatSetPointListVUBufferSize are, either), then the pipeline will default to handling triangles. The input vertex stride will default to 4 quadwords and vuTSVertexMaxCount and vuTLTriangleMaxCount will default to the maximum possible batch sizes for that stride (if you have changed the VIFOffset from the default value then this will not be valid). This function must be called before unlocking the pipeline containing this PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllMatSetVIFOffset is a post construction time node API function which is used to set the VIF offset that is used when processing multiple batches of data. The VIF offset is the address in VU1 memory of the second data input buffer (we upload data in a double-buffered scheme so that upload and calculations can occur in parallel). Its location relies on the size of input batches. (See the 'PS2 Vector Code' white paper for an overview of VU1 memory layout and use) If this function is not called, a value suitable for the default code fragments and static data allocations will be used. For user provided VU1 code, this value can be obtained from the pipeline specific headerfile generated by processing stddata.i This function must be called after unlocking the pipeline containing the PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllMatSetVU1CodeArray is a post construction time node API function which permits setting of the VU1 code fragments to be used by this pipeline. After calling the RxPipelineNodePS2AllMatBridgeCallBack, PS2AllMat.csl will upload and activate (or queue for activation) a VU1 code fragment. It will use the vu1CodeIndex member of the RxPS2AllPipeData struct to select the code fragment to use from the VU1 code array (see RxPipelineNodePS2AllObjectSetupCallBack and RxPipelineNodePS2AllMatBridgeCallBack for details on setting up vu1CodeIndex). The array should contain pointers to callable DMA chain mode packets that will upload code to location 0 onward on VU1. You may provide an array of any length, though naturally the vu1CodeIndex must not select an element beyond its bounds! The purpose of the array is to allow run-time switching between different code fragments to perform different transforms such as clipping, non-clipping, fogging, non-fogging, etcetera. Array elements must not be NULL. If this function is not called, the default null VU1 transforms will be used (these can be reinstated by calling this function with a NULL array pointer - FYI the default null VU1 code array may be accessed through the global variable 'skyVU1NullTransforms'). See RxPipelineNodePS2AllMatBridgeCallBack for the details of the layout of this array. If the null VU1 transforms are used, then the geometry will still be uploaded to the VU1, but the transform will return having submitted nothing to the GS. This function must be called after unlocking the pipeline containing the PS2AllMat.csl node.
|
|
RxPipelineNodePS2AllSetCallBack is a post construction time node API function used to register a callback with a PS2All.csl pipeline node. During its execution, the PS2All.csl node calls several callback functions. Callbacks are also called from the PS2AllMat.csl node in material pipelines (see RxPipelineNodePS2AllMatSetCallBack for details). Here is a list of the callback types (in order of execution within PS2All.csl) used by PS2All.csl: rxPS2ALLCALLBACKOBJECTSETUP - Performs per-object setup (see RxPipelineNodePS2AllObjectSetupCallBack) rxPS2ALLCALLBACKOBJECTFINALIZE - Performs per-object post-render tasks (see RxPipelineNodePS2AllObjectFinalizeCallBack) Here is a list of the default callbacks used within RenderWare for RpAtomics, RpWorldSectors and Im3D, exposed so that you may use them in custom pipelines: RpAtomicPS2AllObjectSetupCallBack, RpWorldSectorPS2AllObjectSetupCallBack, RwIm3DPS2AllObjectSetupCallBack (no RxPipelineNodePS2AllObjectFinalizeCallBack is used by default for RpAtomics, RpWorldSectors or RwIm3D) NOTE: When a PS2All.csl or PS2AllMat.csl pipeline is unlocked, its list of callbacks is initialized to NULL - this means that when constructing such a pipeline, you must explicitly set all required callbacks (the docs for each callback type specify which are required, which are optional and why). This is so that no errors can occur due to accidental reliance on inappropriate default callbacks. There will be ASSERTs at runtime if you omit required callbacks. Here follows an overview of pipeline execution through PS2All.csl (the object pipeline) and PS2AllMat.csl (the material pipeline(s): PS2All.csl performs some per-object processing (through callbacks) and then calls a PS2AllMat.csl-based material pipeline for each mesh in the object. It uses the RxPS2AllPipeData structure to carry data down the pipeline which is useful for all the callbacks which will be executed along the way. For details of the members of this structure, see RxPS2AllPipeData. Some of these members will be initialized by the nodes, some should be initialized by callbacks (see documentation for callback types for more precise details on this), most are modifiable by callbacks. First of all, PS2All.csl calls the RxPipelineNodePS2AllObjectSetupCallBack, which performs tasks such as frustum culling, per-object instance testing and lighting setup. The decision of whether or not to reinstance meshes is controlled in the pipeline by the objInstance and meshInstance members of RxPS2AllPipeData. objInstance is initialized to rxINSTANCEDONTINSTANCE which signifies that no mesh instancing or instance testing is to occur. The RxPipelineNodePS2AllObjectSetupCallBack may clear this flag if it wishes mesh instance testing to occur and may set the rxINSTANCEINPLACEINSTANCE, rxINSTANCECONGRUENTINSTANCE or rxINSTANCEFULLREINSTANCE flags if it wishes in-place, congruent or full (see below) reinstancing to occur for all meshes regardless of mesh instance tests. The meshInstance field is initialized to (the post-object-setup value of) objInstance for all meshes, then processing passes, for each mesh in turn, to material pipelines - containing PS2AllMat.csl. PS2AllMat.csl will first call the RxPipelineNodePS2AllMatMeshInstanceTestCallBack unless meshInstance is set to rxINSTANCEDONTINSTANCE and unless no instance data exists yet (in which case no test is necessary, instancing will definitely have to occur!). This will update meshInstance and if, on exit, rxINSTANCEINPLACEINSTANCE, rxINSTANCECONGRUENTINSTANCE or rxINSTANCEFULLINSTANCE are set then reinstancing will occur. Full reinstancing is performed when the size and layout of instance data has changed and must be recalculated (PS2AllMat.csl will do this). Congruent reinstancing is performed when this is not the case and the size and layout of instance data may be cached. In both cases, a new block of instance data will be allocated and filled, using the RxPipelineNodePS2AllMatResEntryAllocCallBack. In-place instancing is performed 'in-place' in the existing RwResEntry. Modifying instance data in-place will cause a time anomaly (if DMA is running three frames behind the CPU, in-place CPU changes will appear to have their effect three frames 'into the future') but if you still wish to do this then it is more efficient than congruent or full reinstancing (which recreate all the instance data from scratch). In-place data modification could be useful for something like, say, CPU-side particle system animation. For example, you might request the CL_RGBA and CL_XYZ clusters and specify the CL_XYZ cluster as CL_ATTRIB_READWRITE. Then the instance callback could modify the positions of vertices (particles) before they are uploaded to VU1 without incurring the cost of a full (or congruent) reinstance every frame. The RxPipelineNodePS2AllMatInstanceCallBack is used to instance data. This should instance both standard data types and user data types (see RxPS2ClusterType). See RxPipelineNodePS2AllMatInstanceCallBack for details. If rxINSTANCEDONTINSTANCE is set, then the RxPipelineNodePS2AllMatInstanceCallBack will not be called. This is the no instancing 'fast-path' (such a path is always taken if 'persistent instance data' is being used (see RpAtomicInstance), wherein an RpGeometry is instanced into memory outside of the resource arena so that it can be streamed to and read from disk and need never be instanced again). After instancing (assuming it occurred), cache is flushed on instance data (DMA doesn't snoop the cache). Then, the RxPipelineNodePS2AllMatBridgeCallBack is called. This selects which VU1 code should be used for this mesh and sets up material properties (color, texture, etc) and this information is uploaded to VU1. In addition, this callback may perform pipeline-specific tasks that it needs to do every time a given mesh is rendered, such as uploading values into the static memory area on VU1 (e.g. a matrix for environment mapping). Finally, it kicks off the transfer of geometry data to VU1 ('renders' the mesh). An optional RxPipelineNodePS2AllMatPostMeshCallBack is then called to perform any necessary post-render, per-mesh tasks. After all meshes have been processed by PS2AllMat.csl material pipelines, an optional RxPipelineNodePS2AllObjectFinalizeCallBack is called, to perform any necessary post-render, per-object tasks. [Note for completeness: PS2AllMat.csl is never actually executed, it is merely presented as if it is for convenience. In reality, it just holds a list of parameters (such as callbacks) for PS2All.csl to use per-mesh. This is why PS2All.csl and PS2AllMat.csl are only compatible with each other] This function should be called after unlocking the pipeline containing this node.
|
|
RxPipelineNodePS2AllSetLightBufferOffset is a post construction time node API function used to set the address in VU1 memory of the lighting data buffer filled by PS2All.csl. To recap (further details on the layout of VU1 memory may be found in the 'PS2 Vector Code' white paper), static data (16 QuadWords) is at the top of VU1 memory, followed by the lighting buffer (by default 32 QuadWords), followed by a clipping buffer (if the current VU code needs it, it will calculate the appropriate size), followed by output buffers and finally input buffers (the input buffers will be big enough to incorporate geometry batches and, if no clipping is being performed, the output buffers will be big enough to hold as many vertices (of a different stride) as the input buffers). The default location of the lighting data buffer in VU1 memory may be overridden with this function. This may be used to shrink the lighting buffer (allowing for larger input/output/clipping buffers), where it is known that few or no lights need be uploaded, and it may be used to grow the lighting buffer. Growing the lighting buffer may be used to increase the space available for lighting data, where many lights (or larger, custom lights) need to be uploaded, or it may in effect grow the size of the static data area (i.e if the lighting data buffer is moved down in VU1 memory but the same amount of it is used, there will now be free memory just below the static data area). NOTE: The maximum allowed size of lighting buffer (in quadwords) is given by rwPS2ALLMAXLIGHTBUFFERSIZE. NOTE: since the location of the lighting data buffer is specified on a per-object basis, it affects all meshes within the object - hence all VU1 code chunks used by the materials in the current object must work with the specified lighting buffer location. Shrinking the lighting buffer for the benefit of some VU1 code chunks should cause no problems for others, but growing the buffer will most likely require explicit support in all VU1 code chunks used by the current object. If zero is passed to this function then the default PS2All.csl lighting buffer location is restored. This function should be called after unlocking the pipeline containing this node.
|
Converted from CHM to HTML with chm2web Pro 2.85 (unicode) |