-
-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
UPBGE: Use SoA for vertices in RAS_DisplayArray. (#715)
The principle of AoS (array of structure) is to store an element structure in a array e.g: struct Vertex { mt::vec3_packed pos; mt::vec3_packed nor; }; std::vector<Vertex> vertices; This kind of structure is very easy to use and totally tolerated for big structure or small amount of elements, also a reference or a pointer to a Vertex can be passed to any functions. Unfortunatly the memory cache usage is most of the time not efficient. Imagining a function modifying only the position of vertices, at each iteration the Vertex struct will be loaded in cache and only the member pos will be used, so 12 bytes on 24, the left 12 bytes will pollute the cache and cause more cache loads. If our function is modifying all the member of Vertex the cache isn't an issue. The opposite way SoA (structure of array) stores in a structure an array for each member, e.g: struct Vertices { std::vector<mt::vec3_packed> pos; std::vector<mt::vec3_packed> nor; }; With this method passing a vertex to an other function is quite complicated as it ends up passing the Vertices instance and the vertex index to sample pos and nor. But on the cache side, if we back to our function modifying the positions, this function will load cache pages of only position and not waste memory at loading other unused data. Also for the case of modifying positions and normals, the both array will be stored in different cache pages without performance decrease compared to AoS. For CPU using SoA is generally an improvement, for GPU too, excepted for old GPU which might prefer interleaved data but nothing really confirms it. Previously in UPBGE and BGE, the vertices were stored in AoS idiom, UPBGE make more complex the vertices by adding different vertex struct for each combination of UV and color layer. All was accessed through an interface RAS_Vertex which hold a pointer to a RAS_IVertexData, the base class of any vertex data of any format. In the same time RAS_IDisplayArray was an interface to RAS_DisplayArray<VertexData>. By using SoA, RAS_DisplayArray owns a VertexData struct with a list for all vertex members (position, normal, tangent, 8 uv and 8 color), depending on the format some UV and color array are left empty. In the same time function for getting and setting all the member data are added, these function takes a vertex index, UV/color index for uv and color, and for setter a value too. By this way BL_SkinDeformer update the position just by calling RAS_DisplayArray::SetPosition(i, pos) instead of getting the RAS_Vertex via RAS_DisplayArray::GetVertex(i) and calling RAS_Vertex::SetXYZ. With these modifications RAS_DisplayArray<>, RAS_VertexData<> are removed and RAS_BatchDisplayArray doesn't need anymore virtual inheritance. On the conversion side, without RAS_VertexData the structure BL_SharedVertexPredicate used to find similar vertices is now copying the normal, tangent, uv and color data inside. Once a vertex is unique, it is added to the display array through RAS_DisplayArray::AddVertex(pos, nor, tan, uvs, colors, origIndex, flag) which append the vertex data to m_vertexData and construct the vertex info. VBO don't try to re-interleave the data as the time cost is too expensive, instead each member are sent to the VBO one by one, this is proceeded in RAS_StorageVbo::CopyVertexData. An other advantage of SoA is allowing to update only one kind of data, if the positions are modified these data are just copied to the beginning of the VBO without touching of the other data. This technique is used in RAS_StorageVbo::CopyVertexData by checking a modification flag. OpenGL attributes (VAO) are changed too because of the new VBO layout. The RAS_VertexDataMemoryFormat is replaced by RAS_DisplayArrayLayout which is not constant after the display array creation as modifying the size of the array change the offset of each data type in the VBO. In consideration RAS_DisplayArray::GetLayout return a new RAS_DisplayArrayLayout with the proper offsets. To recreate the attributes, RAS_AttributeArray::Clear is called when detecting a size update in RAS_DisplayArrayBucket::UpdateActiveMeshSlots. To summarize the advantages of using SoA are the cache friendly load, the possibility to update only modified data in VBO and the simplification of storing multiple vertex formats. But the inconveniences could be some old GPU limitation and the recreation of the VAO at each display array size update in modifier deformers. This patch was tested with 3 files : The first file is 1600 cubes of 384 faces deformed by an armature. If the cube have only the default UV and color layer : Previous Current Animation 9.6 6.3 Rasterizer 17.5 10.8 With 8 UV and color layers : Previous Current Animation 17.5 6.7 Rasterizer 42.7 11.9 The second and third files are about modification of vertex position from python or rendering a mesh with a huge amount of vertices, both files didn't show a time difference.
- Loading branch information
1 parent
6cc0ea0
commit b6123cc
Showing
63 changed files
with
1,087 additions
and
1,474 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.