#What industry standard GPU skin transformation update/sync

13 messages · Page 1 of 1 (latest)

rugged hornet
#

I'm developing GPU skin system for skeletal meshes. In my implementation final pose for skinning is calculated on CPU side. Question is how to organize skin joint transformation data upload in Vulkan? I mean in Vulkan the developer MUST control situation that resource is valid at the moment of GPU access. Keeping in mind that GPU is async device. It always works in the past from CPU perspective.

I aim to use VkBuffer to upload my skin joint information. What does industry usually do to:

  1. To not consume too much VRAM memory for joint information
  2. Synchronize upload/skin GPU job properly
  3. Correctly stop and destroy all resources (for example at application exit)

Thanks.

hearty edge
#

I'm not sure there's really any one industry-standard solution here. In general you want the final skinning buffer to live in VRAM on a dedicated GPU, which without ReBAR means having the GPU copy it there from SysRAM. Ideally you would probably do that with an async copy/transfer queue rather than a synchronous copy on the graphics timeline, potentially using a generic system that handles these kinds of SysRAM->VRAM updates.

thorn breach
#

Upload an array of float4x3s to a buffer, perhaps a StructuredBuffer (or the Vulkan equivalent).

#

You should be able to create buffers like this in your engine, and upload them for the next frame. There's nothing too special about skinning data here, compared to other kinds of data.

#

One trick you might enjoy for skinning data is that a lot of joints in models aren't used as part of vertex weights at all -- for instance, no vertex is going to be directly parented to the root bone, and you'll probably have a lot of those. So it's best to preprocess your skeleton & mesh to find which ones are actually used by vertex weights, and then only upload the joints that are referenced.

rugged hornet
#

So having two VkBuffers per animation graph is fine? One VkBuffer is used at VkCommandBuffer which is send to GPU, another VkBuffer is able to upload and be used during another VkCommandBuffer during CPU recording stage.

Swap VkBuffers after present and waiting VkCommandBuffer fence.

It's sorda kinda double buffering for joint data.

One important condition the engine itself is using two main VkCommandBuffers for recording on CPU/executing on GPU

rugged hornet
thorn breach
#

Huh?

rugged hornet
thorn breach
#

Sure, so you have multiple objects rendered with the same skeleton.

rugged hornet
# thorn breach Sure, so you have multiple objects rendered with the same skeleton.

It's very common I think judging on my previous experience with Haydee games. Important difference that you suggested to own VkBuffers with joints per skeletal mesh instance instead per animation graph instance. If I understand you correctly It will introduce some logic in skeletal mesh code to select from joints final pose of the animation graph and upload such sparse joints to the GPU. Every single skeletal mesh have to do so. So for example for character above every 10 meshes should upload simplified set of joints to GPU.

In single pose approach it's needed to upload pose only once in animation graph code. Obviously there will be some redundancy at GPU skinning data for every 10 skeletal meshes but all data will be available for skinning on GPU side.

thorn breach
#

What I'm saying is that you have a separate list of joints which are the joints that vertices can weight to -- either a remap table, or a flag on the joints, I don't really care. The vertex data references indices into that list.

#

The "mesh made up of multiple objects" is usually split based on materials, and the vertex data is still shared for the entire mesh, they just split it into multiple draw calls. That said, for games with a lot of player customization, they might use other approaches.