Skip to main content

Overview

The cgcomp tool compiles Cg (C for Graphics) shader programs into RSX-compatible binary format for PlayStation 3 graphics programming. It converts .vcg (vertex) and .fcg (fragment) shader source files into .vpo and .fpo binary programs.
Requires NVIDIA Cg Toolkit installed and accessible (libCg.so / cg.dll).

Shader Types

Vertex Programs (.vcg)

Process vertex data: transformations, lighting calculations, texture coordinate generation.

Fragment Programs (.fcg)

Process pixel data: texturing, per-pixel lighting, color blending, effects.

Command-Line Usage

cgcomp [options] input output

Options

-v
flag
Input is a vertex program (.vcg)
-f
flag
Input is a fragment program (.fcg)
-e
string
Specify entry point function (default: “main”)
-a
flag
Compile from assembly input file (skip Cg compiler)
-d
flag
Dump assembly to file (output.asm)
-Wcg,
string
Pass additional arguments to Cg compiler frontend

Examples

# Compile vertex shader
cgcomp -v shader.vcg shader.vpo

# With custom entry point
cgcomp -v -e vertexMain shader.vcg shader.vpo

# Dump assembly for debugging
cgcomp -v -d shader.vcg shader.vpo
# Creates shader.vpo and shader.vpo.dump

Shader Compilation Pipeline

1

Cg Compilation

Source code is compiled to GPU assembly using NVIDIA Cg compiler:
  • Profile: VP40 for vertex, FP40 for fragment
  • Optimizations: -O3, -fastmath, -fastprecision, -unroll
2

Assembly Parsing

GPU assembly is parsed and analyzed:
  • Extract parameters (uniforms, attributes)
  • Identify branches and relocations
  • Count registers and resources
3

Binary Encoding

Assembly is encoded to RSX binary format:
  • Instruction encoding
  • Constant table generation
  • Metadata embedding
4

Package Creation

Final binary package with header:
  • Magic number (VP/FP)
  • Shader metadata
  • Instruction data
  • Parameter tables

Example Shaders

Basic Vertex Shader

vpshader.vcg
void main(float4 position : POSITION,
          float4 color : COLOR0,
          float2 texcoord : TEXCOORD0,
          
          out float4 oPosition : POSITION,
          out float4 oColor : COLOR0,
          out float2 oTexCoord : TEXCOORD0)
{
    oPosition = position;
    oColor = color;
    oTexCoord = texcoord;
}

Basic Fragment Shader

fpshader.fcg
void main(float4 color : COLOR0,
          float2 texcoord : TEXCOORD0,
          
          uniform sampler2D texture,
          
          out float4 oColor : COLOR0)
{
    float alpha = tex2D(texture, texcoord).w;
    if(alpha <= 0.5f) {
        oColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
    } else {
        oColor.rgb = color.rgb;
        oColor.a = color.a;
    }
}
These examples are from samples/graphics/debugfont_renderer/shaders/

Build System Integration

The PSL1GHT build system automatically compiles shaders via ppu_rules:
# Automatic shader compilation rules
%.vpo: %.vcg
    $(VERB) echo $(notdir $<)
    $(VERB) $(CGCOMP) -v $(CGCFLAGS) $^ $@

%.fpo: %.fcg
    $(VERB) echo $(notdir $<)
    $(VERB) $(CGCOMP) -f $(CGCFLAGS) $^ $@

Makefile Setup

Configure your Makefile to compile shaders:
# Shader directories
SHADERS := shaders

# Shader files
VCGFILES := $(foreach dir,$(SHADERS),$(notdir $(wildcard $(dir)/*.vcg)))
FCGFILES := $(foreach dir,$(SHADERS),$(notdir $(wildcard $(dir)/*.fcg)))

# Compiled outputs
VPOFILES := $(VCGFILES:.vcg=.vpo)
FPOFILES := $(FCGFILES:.fcg=.fpo)

# Include in object files
OFILES := $(addsuffix .o,$(VPOFILES)) \
          $(addsuffix .o,$(FPOFILES)) \
          $(CPPFILES:.cpp=.o) $(CFILES:.c=.o)

Embedding Shaders

Compiled shaders are embedded as binary data:
# Convert shader binaries to object files
%.vpo.o : %.vpo
    @echo $(notdir $<)
    @$(bin2o)

%.fpo.o : %.fpo
    @echo $(notdir $<)
    @$(bin2o)

Using in Code

// External shader binary data
extern const u8 vpshader_vpo[];
extern const u32 vpshader_vpo_size;
extern const u8 fpshader_fpo[];
extern const u32 fpshader_fpo_size;

// Load vertex program
rsxVertexProgram *vp = (rsxVertexProgram*)vpshader_vpo;
rsxLoadVertexProgram(context, vp, vp->ucode);

// Load fragment program
rsxFragmentProgram *fp = (rsxFragmentProgram*)fpshader_fpo;
rsxLoadFragmentProgramFromFile(context, fp, fp->offset);

Compiler Optimization

Default Cg compiler arguments (from tools/cgcomp/source/main.cpp:76):
static const char *cgDefArgs[] = {
    "-O3",              // Maximum optimization
    "-fastmath",        // Fast math operations
    "-fastprecision",   // Reduced precision
    "-unroll",          // Loop unrolling
    "count=8",          // Unroll count
    "-ifcvt",           // If conversion
    "all",              // All if conversions
    NULL
};

Custom Compiler Options

Pass additional options with -Wcg,:
# Disable inlining
cgcomp -v -Wcg,noinline shader.vcg shader.vpo

# Enable debug info
cgcomp -f -Wcg,strict shader.fcg shader.fpo

# Multiple options
cgcomp -v -Wcg,nounroll -Wcg,profile=vp40 shader.vcg shader.vpo

Shader Profiles

PS3 RSX supports these Cg profiles (from main.cpp:56-62):
VP40
profile
Vertex Program profile for RSX (NV40-class)
FP40
profile
Fragment Program profile for RSX (NV40-class)
The PS3 RSX is based on NVIDIA’s NV47 GPU, similar to GeForce 7800.

Binary Format

Vertex Program Binary (VP)

// From compiled output
typedef struct {
    u16 magic;          // 'VP' = 0x5650
    u16 insn_start;     // Instruction start offset
    u16 const_start;    // Constant start index
    u16 num_regs;       // Number of registers used
    u32 input_mask;     // Input attribute mask
    u32 output_mask;    // Output attribute mask
    u32 attr_off;       // Attribute table offset
    u16 num_attr;       // Number of attributes
    u32 const_off;      // Constant table offset
    u16 num_const;      // Number of constants
    u32 ucode_off;      // Microcode offset
    u16 num_insn;       // Number of instructions
} rsxVertexProgram;

Fragment Program Binary (FP)

typedef struct {
    u16 magic;          // 'FP' = 0x4650
    u16 num_regs;       // Number of registers
    u32 fp_control;     // Fragment program control
    u16 texcoords;      // Texture coordinate mask
    u16 texcoord2D;     // 2D texture mask
    u16 texcoord3D;     // 3D texture mask
    u32 attr_off;       // Attribute offset
    u16 num_attr;       // Number of attributes
    u32 const_off;      // Constant offset
    u16 num_const;      // Number of constants
    u32 ucode_off;      // Microcode offset
    u16 num_insn;       // Number of instructions
} rsxFragmentProgram;

Debugging Shaders

Dump Assembly

# Generate assembly dump
cgcomp -v -d shader.vcg shader.vpo

# View the assembly
cat shader.vpo.dump
Example output:
!!ARBvp1.0
ATTRIB v0 = vertex.position;
ATTRIB v1 = vertex.color;
ATTRIB v2 = vertex.texcoord[0];
OUTPUT o0 = result.position;
OUTPUT o1 = result.color;
OUTPUT o2 = result.texcoord[0];

MOV o0, v0;
MOV o1, v1;
MOV o2, v2;
END

Common Errors

Install NVIDIA Cg Toolkit:
# Linux
sudo apt-get install nvidia-cg-toolkit

# Or download from NVIDIA website
# Set LD_LIBRARY_PATH to Cg lib directory
export LD_LIBRARY_PATH=/opt/nvidia-cg-toolkit/lib:$LD_LIBRARY_PATH
Check Cg syntax errors in the output:
cgcomp -v shader.vcg shader.vpo 2>&1 | less
Common issues:
  • Syntax errors in shader code
  • Unsupported functions for VP40/FP40
  • Too many instructions or registers
The compiled shader may exceed hardware limits:
  • Vertex programs: Max ~512 instructions
  • Fragment programs: Max texture samplers, registers
  • Try simplifying shader or splitting into multiple passes

Advanced Example: Diffuse + Specular

void main(float4 position : POSITION,
          float3 normal : NORMAL,
          float2 texcoord : TEXCOORD0,
          
          uniform float4x4 modelViewProj,
          uniform float4x4 modelView,
          uniform float3x3 normalMatrix,
          
          out float4 oPosition : POSITION,
          out float3 oNormal : TEXCOORD0,
          out float3 oViewVec : TEXCOORD1,
          out float2 oTexCoord : TEXCOORD2)
{
    oPosition = mul(modelViewProj, position);
    oNormal = normalize(mul(normalMatrix, normal));
    
    float3 viewPos = mul(modelView, position).xyz;
    oViewVec = -viewPos;
    
    oTexCoord = texcoord;
}

Source Code Reference

The cgcomp implementation:
  • Main: tools/cgcomp/source/main.cpp:1-582
  • VP Compiler: tools/cgcomp/source/compilervp.cpp
  • FP Compiler: tools/cgcomp/source/compilerfp.cpp
  • VP Parser: tools/cgcomp/source/vpparser.cpp
  • FP Parser: tools/cgcomp/source/fpparser.cpp

Key Functions

// From tools/cgcomp/source/main.cpp:221
int compileVP() {
    // Create Cg context and compile vertex program
    // Parse assembly output
    // Encode to RSX binary format
    // Write .vpo file
}

// From tools/cgcomp/source/main.cpp:382
int compileFP() {
    // Create Cg context and compile fragment program
    // Parse assembly output
    // Encode to RSX binary format
    // Write .fpo file
}

See Also

RSX Graphics

Using compiled shaders with RSX

Build System

Automating shader compilation

Graphics Samples

Complete shader examples

Cg Language

Cg language reference (external)

Build docs developers (and LLMs) love