group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
SkinnedRenderer Class Reference

Instanced GPU-skinning subsystem. One per renderer. More...

#include <SkinnedRenderer.hpp>

Collaboration diagram for SkinnedRenderer:
[legend]

Classes

struct  SkinnedMesh
 One mesh of the installed skinned rig. More...
struct  SsboInfo

Public Member Functions

 SkinnedRenderer ()=default
 ~SkinnedRenderer ()=default
 SkinnedRenderer (const SkinnedRenderer &)=delete
SkinnedRendereroperator= (const SkinnedRenderer &)=delete
 SkinnedRenderer (SkinnedRenderer &&)=delete
SkinnedRendereroperator= (SkinnedRenderer &&)=delete
void init (SDL_GPUDevice *device, SDL_GPUTextureFormat &colorTarget, const SDL_GPUShaderFormat &shaderFormat)
 Bind the SDL GPU device.
bool setRig (const std::vector< RigMeshSource > &meshes, int numJoints)
 Install the shared character rig.
void setFrame (const std::vector< glm::mat4 > &palette, const std::vector< SkinnedInstance > &instances)
 Push this frame's per-character bone palette + per-instance data.
void uploadFrame (SDL_GPUCommandBuffer *cmd, SDL_GPUCopyPass *copyPass)
 Upload this frame's palette + instance buffers to the GPU.
void draw (SDL_GPURenderPass *renderPass, SDL_GPUCommandBuffer *cmd)
 Issue the instanced draws for every visible skinned character.
void shutdown ()
 Release all GPU resources owned by this subsystem.
int numJoints () const
 Number of joints in the installed rig (0 if not installed).
bool rigInstalled () const
 True after a successful setRig.
size_t pendingInstanceCount () const
 Number of instances pending render this frame (0 if no frame submitted).

Private Member Functions

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)

Private Attributes

SDL_GPUDevice * device_ = nullptr
SDL_GPUGraphicsPipeline * pipeline_ = nullptr
 The skinned graphics pipeline.
bool rigInstalled_ = false
int numJoints_ = 0
std::vector< SkinnedMeshskinnedMeshes_
SsboInfo palettesSsboInfo_
SsboInfo instancesSsboInfo_
SDL_GPUTransferBuffer * paletteXfer_ = nullptr
SDL_GPUTransferBuffer * instanceXfer_ = nullptr
Uint32 paletteXferCapacityBytes_ = 0
Uint32 instanceXferCapacityBytes_ = 0
std::vector< glm::mat4 > framePalette_
std::vector< SkinnedInstanceframeInstances_
bool frameDirty_ = false

Detailed Description

Instanced GPU-skinning subsystem. One per renderer.

Constructor & Destructor Documentation

◆ SkinnedRenderer() [1/3]

SkinnedRenderer::SkinnedRenderer ( )
default
Here is the caller graph for this function:

◆ ~SkinnedRenderer()

SkinnedRenderer::~SkinnedRenderer ( )
default

◆ SkinnedRenderer() [2/3]

SkinnedRenderer::SkinnedRenderer ( const SkinnedRenderer & )
delete
Here is the call graph for this function:

◆ SkinnedRenderer() [3/3]

SkinnedRenderer::SkinnedRenderer ( SkinnedRenderer && )
delete
Here is the call graph for this function:

Member Function Documentation

◆ createSkinningPipeline()

bool SkinnedRenderer::createSkinningPipeline ( SDL_GPUTextureFormat & colorTarget,
const SDL_GPUShaderFormat & shaderFormat )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ draw()

void SkinnedRenderer::draw ( SDL_GPURenderPass * renderPass,
SDL_GPUCommandBuffer * cmd )

Issue the instanced draws for every visible skinned character.

Parameters
renderPassThe active main HDR (or swapchain) render pass.
cmdThe 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.

Here is the caller graph for this function:

◆ 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
deviceBorrowed; the device must outlive this SkinnedRenderer.
Here is the call graph for this function:

◆ numJoints()

int SkinnedRenderer::numJoints ( ) const
inlinenodiscard

Number of joints in the installed rig (0 if not installed).

Here is the caller graph for this function:

◆ operator=() [1/2]

SkinnedRenderer & SkinnedRenderer::operator= ( const SkinnedRenderer & )
delete
Here is the call graph for this function:

◆ operator=() [2/2]

SkinnedRenderer & SkinnedRenderer::operator= ( SkinnedRenderer && )
delete
Here is the call graph for this function:

◆ 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
paletteFlat array, sized numInstances * numJoints (mat4 each).
instancesOne 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>:

  1. For each visible character compute worldTransform = T(pos) * R(yaw) * S(scale).
  2. palette[slot * numJoints .. (slot+1) * numJoints] = animator.skinMatrices().
  3. 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
meshesOne source-mesh entry per skinned mesh in the rig (typically 1-3 for humanoid rigs).
numJointsNumber 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.

Here is the call graph for this function:

◆ 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
cmdFrame command buffer.
copyPassAn 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.

Here is the call graph for this function:

Member Data Documentation

◆ device_

SDL_GPUDevice* SkinnedRenderer::device_ = nullptr
private

◆ frameDirty_

bool SkinnedRenderer::frameDirty_ = false
private

◆ frameInstances_

std::vector<SkinnedInstance> SkinnedRenderer::frameInstances_
private

◆ 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: