Instanced GPU-skinning subsystem. One per renderer.
More...
#include <SkinnedRenderer.hpp>
|
| bool | ensureSsbos (Uint32 paletteBytes, Uint32 instanceBytes) |
| | Grow palette/instance SSBOs (and their transfer buffers) to at least these byte sizes.
|
| bool | createSkinningPipeline (SDL_GPUTextureFormat &colorTarget, const SDL_GPUShaderFormat &shaderFormat) |
Instanced GPU-skinning subsystem. One per renderer.
◆ SkinnedRenderer() [1/3]
| SkinnedRenderer::SkinnedRenderer |
( |
| ) |
|
|
default |
◆ ~SkinnedRenderer()
| SkinnedRenderer::~SkinnedRenderer |
( |
| ) |
|
|
default |
◆ SkinnedRenderer() [2/3]
◆ SkinnedRenderer() [3/3]
◆ createSkinningPipeline()
| bool SkinnedRenderer::createSkinningPipeline |
( |
SDL_GPUTextureFormat & | colorTarget, |
|
|
const SDL_GPUShaderFormat & | shaderFormat ) |
|
private |
◆ draw()
| void SkinnedRenderer::draw |
( |
SDL_GPURenderPass * | renderPass, |
|
|
SDL_GPUCommandBuffer * | cmd ) |
Issue the instanced draws for every visible skinned character.
- Parameters
-
| renderPass | The active main HDR (or swapchain) render pass. |
| cmd | The frame command buffer. |
Called from NewRenderer::drawFrame INSIDE the geometry pass. Currently a no-op placeholder — see cpp for the algorithm sketch.
◆ ensureSsbos()
| bool SkinnedRenderer::ensureSsbos |
( |
Uint32 | paletteBytes, |
|
|
Uint32 | instanceBytes ) |
|
private |
Grow palette/instance SSBOs (and their transfer buffers) to at least these byte sizes.
◆ init()
| void SkinnedRenderer::init |
( |
SDL_GPUDevice * | device, |
|
|
SDL_GPUTextureFormat & | colorTarget, |
|
|
const SDL_GPUShaderFormat & | shaderFormat ) |
Bind the SDL GPU device.
Call from NewRenderer::init once the device exists. Does NOT allocate any GPU resources yet; those are created lazily on the first setRig / setFrame call.
- Parameters
-
◆ numJoints()
| int SkinnedRenderer::numJoints |
( |
| ) |
const |
|
inlinenodiscard |
Number of joints in the installed rig (0 if not installed).
◆ operator=() [1/2]
◆ operator=() [2/2]
◆ pendingInstanceCount()
| size_t SkinnedRenderer::pendingInstanceCount |
( |
| ) |
const |
|
inlinenodiscard |
Number of instances pending render this frame (0 if no frame submitted).
◆ rigInstalled()
| bool SkinnedRenderer::rigInstalled |
( |
| ) |
const |
|
inlinenodiscard |
True after a successful setRig.
◆ setFrame()
| void SkinnedRenderer::setFrame |
( |
const std::vector< glm::mat4 > & | palette, |
|
|
const std::vector< SkinnedInstance > & | instances ) |
Push this frame's per-character bone palette + per-instance data.
- Parameters
-
| palette | Flat array, sized numInstances * numJoints (mat4 each). |
| instances | One entry per visible character. paletteBase of entry i MUST equal i * numJoints so the shader's index math works. |
IMPLEMENTATION (real, wired):
DATA SOURCE: Game.cpp's per-frame animation block walks the ECS view <AnimatedCharacter, Position, Velocity, PlayerVisState, InputSnapshot>:
- For each visible character compute worldTransform = T(pos) * R(yaw) * S(scale).
- palette[slot * numJoints .. (slot+1) * numJoints] = animator.skinMatrices().
- instances[slot] = {worldTransform, paletteBase=slot*numJoints, tint}.
CONSUMER: the (not-yet-written) skinned vertex shader reads: instances[gl_InstanceIndex] → worldTransform + paletteBase palette[paletteBase + boneIndices.k] → bone matrix k (k = 0..3)
◆ setRig()
| bool SkinnedRenderer::setRig |
( |
const std::vector< RigMeshSource > & | meshes, |
|
|
int | numJoints ) |
Install the shared character rig.
Call ONCE after init.
- Parameters
-
| meshes | One source-mesh entry per skinned mesh in the rig (typically 1-3 for humanoid rigs). |
| numJoints | Number of skeleton joints. Determines per-instance palette stride in the shader. |
- Returns
- True on success. False if already installed, or upload failed.
IMPLEMENTATION (real, wired):
- Iterates meshes, creating three GPU buffers per mesh: slot 0: bind-pose vertices (ModelVertex, 48 bytes/vert) — VERTEX usage slot 1: bone influences (BoneInfluence, 32 bytes/vert) — VERTEX usage slot 2: indices (uint32_t, 4 bytes each) — INDEX usage Saves them in skinnedMeshes_.
- Stores numJoints in numJoints_; sets rigInstalled_.
- Does NOT allocate palette/instance SSBOs — those grow lazily on the first setFrame call.
DATA SOURCE: Game.cpp builds vector<RigMeshSource> from CharacterRig::meshes() (animation/CharacterRig.hpp) once after the rig FBX loads. See RigMeshSource in RendererTypes.hpp for the layout.
◆ shutdown()
| void SkinnedRenderer::shutdown |
( |
| ) |
|
Release all GPU resources owned by this subsystem.
Called from NewRenderer::quit (BEFORE the device is destroyed).
◆ uploadFrame()
| void SkinnedRenderer::uploadFrame |
( |
SDL_GPUCommandBuffer * | cmd, |
|
|
SDL_GPUCopyPass * | copyPass ) |
Upload this frame's palette + instance buffers to the GPU.
- Parameters
-
| cmd | Frame command buffer. |
| copyPass | An open copy pass on cmd. |
Called from NewRenderer::drawFrame BEFORE the main render pass begins so the copy is sequenced ahead of the draws. Uses cycle=true on the transfer-buffer map so we never stall waiting on last frame's GPU read of the SSBO.
◆ device_
| SDL_GPUDevice* SkinnedRenderer::device_ = nullptr |
|
private |
◆ frameDirty_
| bool SkinnedRenderer::frameDirty_ = false |
|
private |
◆ frameInstances_
◆ framePalette_
| std::vector<glm::mat4> SkinnedRenderer::framePalette_ |
|
private |
◆ instancesSsboInfo_
| SsboInfo SkinnedRenderer::instancesSsboInfo_ |
|
private |
◆ instanceXfer_
| SDL_GPUTransferBuffer* SkinnedRenderer::instanceXfer_ = nullptr |
|
private |
◆ instanceXferCapacityBytes_
| Uint32 SkinnedRenderer::instanceXferCapacityBytes_ = 0 |
|
private |
◆ numJoints_
| int SkinnedRenderer::numJoints_ = 0 |
|
private |
◆ palettesSsboInfo_
| SsboInfo SkinnedRenderer::palettesSsboInfo_ |
|
private |
◆ paletteXfer_
| SDL_GPUTransferBuffer* SkinnedRenderer::paletteXfer_ = nullptr |
|
private |
◆ paletteXferCapacityBytes_
| Uint32 SkinnedRenderer::paletteXferCapacityBytes_ = 0 |
|
private |
◆ pipeline_
| SDL_GPUGraphicsPipeline* SkinnedRenderer::pipeline_ = nullptr |
|
private |
The skinned graphics pipeline.
TODO(graphics): create this in init (or lazily on first frame) with two vertex buffers (ModelVertex, BoneInfluence), two vertex storage buffers (palette, instances), one vertex UBO (view-projection), depth test on, cull mode NONE.
◆ rigInstalled_
| bool SkinnedRenderer::rigInstalled_ = false |
|
private |
◆ skinnedMeshes_
| std::vector<SkinnedMesh> SkinnedRenderer::skinnedMeshes_ |
|
private |
The documentation for this class was generated from the following files: