About This Page

Covers PlayStation 4 and PlayStation 5 console development. Main page: Console Development. See also: Console Development - Xbox, Console Development - Nintendo Switch, Console Development - Certification.

NDA Notice

Official PlayStation SDK details are under NDA. This page covers publicly documented features, architecture concepts, and general best practices from GDC talks, official PS5 hardware documentation, and open resources.

PlayStation Architecture

PS5 Hardware Deep Dive

PS5 Custom Silicon (AMD "Oberon"):

CPU:
  8 × AMD Zen 2 cores @ 3.5 GHz (variable, 2.23 GHz min)
  SMT (Hyper-Threading) enabled — 16 logical threads
  L3 cache: 32 MB

GPU:
  36 Compute Units @ 2.23 GHz
  10.3 TFLOPS FP32 performance
  RDNA 2 architecture
  Hardware Ray Tracing (BVH traversal in hardware)
  Mesh Shaders
  Variable Rate Shading (VRS)
  Sampler Feedback

Memory:
  16 GB GDDR6 @ 448 GB/s
  ~14 GB available to developers (OS uses ~2 GB)
  Unified memory — CPU and GPU share the same pool
  No separate VRAM — unified architecture

Storage:
  Custom NVMe SSD: 5.5 GB/s raw read speed
  ~8–9 GB/s with built-in Kraken decompression
  Hardware decompression coprocessor (runs in parallel with CPU/GPU)

Audio:
  Tempest 3D Audio Engine (custom audio DSP)
  3D positional audio without CPU cost
  HRTF-based spatial audio for headphones and TV

PS5 vs PS4 Key Differences

FeaturePS4PS4 ProPS5
CPU8-core Jaguar 1.6 GHz8-core Jaguar 2.1 GHz8-core Zen 2 3.5 GHz
GPU1.84 TFLOPS GCN4.2 TFLOPS GCN10.3 TFLOPS RDNA 2
RAM8 GB GDDR58 GB GDDR516 GB GDDR6
SSD SpeedHDD ~100 MB/sHDD ~100 MB/s5,500 MB/s
Ray TracingNoneNoneHardware RT
DualShockDualShock 4DualShock 4DualSense

PS5 Memory Architecture

PS5 Unified Memory Pools:

GPU Main Pool (~10 GB recommended for GPU assets):
  Textures, render targets, meshes, shaders
  High-bandwidth — 448 GB/s access
  Allocated via GNM memory allocator

CPU/GPU Shared Pool (~4 GB):
  Game logic data, audio, streaming buffers
  Accessible by both CPU and GPU
  Lower bandwidth than pure GPU pool

Flexible Memory:
  PS5 allows dynamic reallocation between pools
  Useful for streaming — free CPU data once GPU loaded

Memory Budget Breakdown (example 3D game):
  Textures (streaming)     3,500 MB
  Render targets           1,200 MB
  Geometry buffers           800 MB
  Audio streaming            256 MB
  Game simulation data     1,000 MB
  Constant buffers           128 MB
  OS / drivers             2,048 MB
  TOTAL                  ~ 8,932 MB (safe under 14 GB)

PlayStation Graphics API

GNM / GNMX Overview

PlayStation uses a proprietary graphics API:

GNM  — Low-level GPU API (explicit, like Vulkan)
  Direct GPU command buffer writing
  No driver overhead
  Maximum performance
  Steep learning curve

GNMX — Higher-level wrapper over GNM
  Handles common patterns automatically
  Closer to DirectX 12 / Vulkan in feel
  Used by most PS5 titles

Gnm::ShaderBinary  — Compiled shader object
Gnm::Buffer        — GPU buffer resource
Gnm::Texture       — Texture resource
Gnm::RenderTarget  — Framebuffer output
Gnm::DrawCommandBuffer — GPU command list
// Conceptual GNMX pipeline setup (structure, not actual SDK)
 
// 1. Create command buffer
sce::Gnmx::GfxContext gfxContext;
gfxContext.init(commandBuffer, commandBufferSize);
 
// 2. Set pipeline state
gfxContext.setActiveShaderStages(
    sce::Gnm::kActiveShaderStagesVsPs);
 
// 3. Bind vertex shader
sce::Gnmx::ShaderInfo vsInfo;
vsInfo.init(&myVertexShader, sizeof(myVertexShader));
gfxContext.setVsShader(vsInfo.m_shader, vsInfo.m_offsetInDwords);
 
// 4. Set vertex buffer
sce::Gnm::Buffer vertexBuffer;
vertexBuffer.initAsVertexBuffer(
    vertexData, sce::Gnm::kDataFormatR32G32B32Float, stride, count);
gfxContext.setVertexBuffers(
    sce::Gnm::kShaderStageVs, 0, 1, &vertexBuffer);
 
// 5. Draw
gfxContext.drawIndex(indexCount, indexData);
 
// 6. Submit to GPU
sce::Gnm::submitCommandBuffers(1, &gfxContext.m_dcb.m_beginptr, ...);

PSSL — PlayStation Shading Language

// PSSL is HLSL-compatible — DirectX shader devs feel at home
 
// Vertex Shader
struct VS_INPUT {
    float4 position : POSITION;
    float3 normal   : NORMAL;
    float2 texCoord : TEXCOORD0;
};
 
struct VS_OUTPUT {
    float4 position : S_POSITION;
    float3 normal   : TEXCOORD0;
    float2 texCoord : TEXCOORD1;
};
 
cbuffer Transform : register(b0) {
    float4x4 worldViewProj;
    float4x4 world;
};
 
VS_OUTPUT main(VS_INPUT input) {
    VS_OUTPUT output;
    output.position = mul(worldViewProj, input.position);
    output.normal   = mul((float3x3)world, input.normal);
    output.texCoord = input.texCoord;
    return output;
}
 
// Fragment (Pixel) Shader
Texture2D albedoTex : register(t0);
SamplerState linearSampler : register(s0);
 
float4 main(VS_OUTPUT input) : S_TARGET_OUTPUT {
    float3 color = albedoTex.Sample(linearSampler, input.texCoord).rgb;
    // Simple diffuse lighting
    float3 lightDir = normalize(float3(0.5, 1.0, 0.5));
    float  diff     = max(dot(normalize(input.normal), lightDir), 0.0);
    return float4(color * diff, 1.0);
}

PS5 Mesh Shaders

// Mesh Shaders replace Vertex + Geometry pipeline
// Better for complex geometry (vegetation, LODs, culling)
 
// Task Shader (Amplification) — runs per meshlet group
[numthreads(32, 1, 1)]
void taskMain(
    uint3 dispatchID : SV_DispatchThreadID,
    out TaskOutput taskOutput)
{
    // Frustum cull meshlets before mesh shader runs
    bool visible = IsVisible(dispatchID.x);
    taskOutput.dispatchGrid = visible ? 1 : 0;
}
 
// Mesh Shader — replaces vertex shader
[outputtopology("triangle")]
[numthreads(64, 1, 1)]
void meshMain(
    uint3 threadID : SV_DispatchThreadID,
    out vertices MeshVertex verts[64],
    out indices  uint3      tris[126])
{
    // Process one meshlet (64 verts, 126 triangles max)
    verts[threadID.x].position = TransformVertex(threadID.x);
    if (threadID.x < 126)
        tris[threadID.x] = GetTriangle(threadID.x);
}

PS5 Ray Tracing

PS5 Hardware Ray Tracing:
  BVH traversal accelerated in hardware (RDNA 2 RT units)
  Ray Box intersection — hardware
  Ray Triangle intersection — hardware
  Shading — programmable (PSSL shader)

Common RT uses on PS5:
  Reflections    — replace screen-space reflections (SSR)
  Shadows        — soft shadows from area lights
  Ambient Occlusion — replace SSAO
  Global Illumination — supplement baked lighting

Performance targets:
  Reflection rays:  1 ray per pixel @ 1080p upscaled to 4K
  Shadow rays:      0.25 rays per pixel (quarter-res, denoised)
  Full path trace:  Not viable in real-time on current gen

PS5 RT API flow (concept):
  1. Build BVH from scene geometry (BLAS per mesh, TLAS per scene)
  2. Set RT pipeline (ray gen, closest hit, miss, any hit shaders)
  3. Bind acceleration structure
  4. DispatchRays(width, height, depth)
  5. Denoise output (temporal accumulation, SVGF)

PS5 SSD & Streaming

I/O Architecture

PS5 Custom I/O Stack:

Physical SSD → Crypto Engine → Kraken Decompressor → RAM
                                     ↓
                             Decompressed directly to GPU
                             (no CPU involved in I/O path!)

Key numbers:
  Raw read:         5.5 GB/s
  Compressed read:  ~8-9 GB/s (2:1 ratio typical game data)
  Decompressor:     Hardware coprocessor, 0 CPU cost

Practical impact:
  A 100 MB level chunk loads in ~18ms at raw speed
  No loading screens between areas if designed for streaming
  Texture streaming at full 4K quality without pre-baked workarounds
// PS5 File I/O — conceptual async file read pattern
 
// 1. Open file
SceNpFile* fileHandle = nullptr;
sceNpFsOpen("/hostapp/levels/level01.pak", 
            SCE_NP_FS_O_RDONLY, &fileHandle);
 
// 2. Async read directly to GPU memory
SceNpFsReadRequest request;
request.buf    = gpuMemoryPtr;  // Direct to GPU — no CPU copy!
request.nbytes = fileSize;
request.offset = 0;
 
SceNpFsIoRequest ioReq;
sceNpFsReadAsync(fileHandle, &request, &ioReq);
 
// 3. Do other work while loading...
 
// 4. Wait for completion
SceNpFsIoResult result;
sceNpFsWaitIoRequest(&ioReq, &result);
 
// 5. Asset is now in GPU memory — draw it

Streaming Strategy

Asset streaming best practices for PS5:

1. Virtual Geometry (Nanite-style):
   Stream geometry at multiple LODs
   PS5 SSD speed makes this practical
   Eliminate pop-in by loading at travel speed

2. Virtual Textures:
   Only load visible texture tiles
   PS5 Sampler Feedback identifies needed tiles
   Reduces texture memory from 10 GB to 2–3 GB

3. Audio Streaming:
   Never load full music tracks — stream from SSD
   ~5-10 MB/s for high-quality stereo audio
   Tiny fraction of SSD bandwidth

4. Level Streaming:
   Async load next level chunks as player approaches boundaries
   Target: load chunk in < 30ms (invisible to player)
   PS5 SSD makes this realistic without LOD degradation

DualSense Controller

Haptic Feedback System

DualSense uses voice-coil actuators (not standard rumble motors):

Standard Rumble (PS4 DualShock 4):
  Two vibration motors — rough on/off vibration
  Low frequency (whole controller shakes)

DualSense HD Rumble:
  Two high-precision voice coil actuators
  Frequency range: 5 Hz to 300 Hz
  Create texture sensations, not just rumble
  Left and right actuators controlled independently

Haptic examples:
  Walking on grass: soft, random low-frequency pulses
  Walking on gravel: irregular high-frequency crunch pattern
  Rain on surface: rapid, dense high-frequency patter
  Heartbeat: rhythmic thump at actual heart rate BPM
  UI hover: single sharp tap (like clicking a physical button)
// DualSense haptics — conceptual C++ usage
 
// Simple haptic impulse
ScePadVibrationParam vibration;
vibration.largeMotor = 180;  // 0-255 intensity
vibration.smallMotor = 100;  // 0-255 intensity
scePadSetVibration(padHandle, &vibration);
 
// Audio-based haptics (advanced — trigger from audio waveform)
ScePadAudioOutParam audioHaptic;
audioHaptic.hapticIntensity = 255;
audioHaptic.outputBuffer    = hapticWaveformData;
audioHaptic.size            = waveformSize;
scePadSetAudioOut(padHandle, &audioHaptic);
 
// Stop vibration
ScePadVibrationParam stopVibration = {0, 0};
scePadSetVibration(padHandle, &stopVibration);

Adaptive Triggers

Trigger modes:

Off:
  No resistance — trigger moves freely

Feedback:
  Vibrate at a specific trigger position
  Parameters: start position, strength

Weapon (Rigid):
  Resist from start position until threshold, then release
  Simulates: bow draw, spring compression, gun trigger
  Parameters: start position, end position (snap point)

Vibration:
  Continuous vibration at specified frequency
  Simulates: engine vibration, electrical buzz

Multiple Positions:
  Set resistance at multiple points along trigger travel
  Complex feedback for simulating textured surfaces
// Adaptive trigger — bow draw example (conceptual)
 
ScePadTriggerEffectParam triggerParam;
memset(&triggerParam, 0, sizeof(triggerParam));
 
// Right trigger = pull bow
triggerParam.triggerMask = SCE_PAD_TRIGGER_EFFECT_TRIGGER_MASK_R2;
triggerParam.command[SCE_PAD_TRIGGER_EFFECT_PARAM_INDEX_FOR_R2]
    .mode = SCE_PAD_TRIGGER_EFFECT_MODE_WEAPON;
triggerParam.command[SCE_PAD_TRIGGER_EFFECT_PARAM_INDEX_FOR_R2]
    .commandData.weaponParam.startPosition = 10; // 0-9
triggerParam.command[SCE_PAD_TRIGGER_EFFECT_PARAM_INDEX_FOR_R2]
    .commandData.weaponParam.endPosition   = 80; // 0-9
triggerParam.command[SCE_PAD_TRIGGER_EFFECT_PARAM_INDEX_FOR_R2]
    .commandData.weaponParam.strength[0]   = 5;  // 0-8
 
scePadSetTriggerEffect(padHandle, &triggerParam);

Trophy System

Trophy Types & Structure

TrophyIconPoints (PSN)Notes
Bronze🥉15Most common
Silver🥈30Mid-tier challenges
Gold🥇90Major milestones
Platinum🏆180Earn all other trophies
Trophy set requirements:
  Every PS4/PS5 game MUST have at least one trophy set
  Must include one Platinum trophy (if 2+ gold trophies)
  Maximum 100 trophies per set (base game)
  DLC can add additional trophy sets
  Total value determines game's PSN Level contribution

Good trophy design:
  Story trophies: awarded for completing major story beats
  Exploration: find all collectibles, discover all areas
  Challenge: complete game on hardest difficulty
  Mastery: max out a character, craft all items
  Humor: find the developer Easter egg, die 100 times
  
Poor trophy design (avoid):
  Online-only trophies (online servers may go offline)
  Missable trophies with no workaround
  Grind trophies requiring 100+ hours of repetitive play

Trophy Implementation

// Trophy unlock — conceptual flow
 
// 1. Initialize trophy system at game start
SceNpTrophyContext trophyContext;
SceNpTrophyHandle  trophyHandle;
 
sceNpTrophyCreateContext(
    &trophyContext, userId, serviceLabel, 0);
sceNpTrophyCreateHandle(&trophyHandle);
 
// 2. Register trophies (reads TROPHY.TRP file)
sceNpTrophyRegisterContext(
    trophyContext, trophyHandle, 0);
 
// 3. Unlock trophy when condition met
void UnlockTrophy(int trophyId) {
    SceNpTrophyId id = trophyId;
    SceNpTrophyId platinumId;
    
    // Returns platinum ID if this unlock earns the platinum
    SceInt32 result = sceNpTrophyUnlockTrophy(
        trophyContext, trophyHandle, id, &platinumId);
    
    if (result == SCE_OK) {
        if (platinumId != SCE_NP_TROPHY_INVALID_TROPHY_ID) {
            // Player also earned platinum!
            ShowPlatinumNotification();
        }
    }
}
 
// Call when player finishes first level:
UnlockTrophy(TROPHY_FIRST_LEVEL_COMPLETE);

Razor Profiler

What is Razor?

Razor is PlayStation's official GPU profiler for PS4/PS5.

Key features:
  GPU Timeline — see every draw call on a frame timeline
  Hardware Counters — GPU utilization %, cache hit rates
  Memory Tracker — see all GPU allocations live
  Shader Inspector — see compiled shader stats (ALU ops, registers)
  Snapshot mode — capture single frames for deep analysis

Workflow:
  1. Run game on dev kit with Razor target process
  2. Connect PC Razor client to dev kit over network
  3. Press capture button — freezes one frame
  4. Analyze draw call order, shader costs, memory
  5. Identify bottleneck (vertex bound? pixel bound? bandwidth?)

Common findings:
  Too many small draw calls → batch or use instancing
  Shader ALU bound → simplify shader math
  Texture bandwidth bound → use compressed formats, mipmaps
  Depth buffer overdraw → add depth prepass

GPU Bottleneck Identification

How to identify what's limiting your frame:

Vertex Bound:
  Symptom: Reducing polygon count improves FPS dramatically
  Fix: LOD system, mesh simplification, instancing

Pixel / Fragment Bound:
  Symptom: Reducing resolution significantly improves FPS
  Fix: Simplify pixel shaders, reduce overdraw, use depth prepass

Bandwidth Bound:
  Symptom: Reducing texture resolution helps more than shader math
  Fix: Texture compression (BC7/ASTC), mipmaps, texture atlases

Compute Bound:
  Symptom: Removing complex post-processing helps
  Fix: Move to async compute, simplify effects, use approximations

PS5 Tiled Architecture:
  GPU processes image in tiles — data fits in on-chip memory
  Avoid clearing render targets with clear color mid-pass
  Use STORE_ACTION_NONE when RT not needed after pass

PS5 Development in Unity & Unreal

Unity on PS5

Unity PS5 requirements:
  Unity 2021.3+ with PS5 build support package
  PlayStation Partner account + SDK
  PS5 GDK development environment

PS5-specific Unity features:
  Adaptive Trigger API    — Haptics.SetTriggerEffect()
  DualSense Haptics API  — Haptics.Play()
  Tempest 3D Audio       — AudioListener.spatializePostEffects
  PS5 Trophy Service     — PS5Trophy.UnlockTrophy()
  Activity Cards         — in-game help cards in PS5 UI
  Game Help system       — hint videos shown from PS5 home menu

Unity PS5 Build:
  Build target: PS5 (appears after SDK installation)
  Output: .pkg file (PlayStation package)
  Install to dev kit via Neighbourhood tool or USB

Unreal Engine on PS5

Unreal Engine 5 on PS5:
  Nanite — virtual geometry, works excellently with PS5 SSD
  Lumen — dynamic GI, runs at 30 FPS on PS5, 60 FPS in perf mode
  Chaos Physics — multi-threaded, uses all 8 Zen 2 cores
  MetaSounds — audio system, leverages Tempest 3D audio

PS5-specific UE5 features:
  DualSense plugin — adaptive triggers, haptics
  PS5 Activity plugin — Activity Cards support
  Console-specific rendering paths — auto-configures for PS5 GPU
  Platform SDH — Sony development hardware integration

UE5 PS5 Build:
  Target platform: PS5
  Uses GNM/GNMX via UE5 RHI (Rendering Hardware Interface)
  Packaging creates .pkg via PlayStation SDK tools