Yotsuba Shader
Documentation

Article

Understanding Yotsuba Shader

Discover how a C# class becomes a shader: the language, the intermediate representation and the compiler.

Overview#

Yotsuba Shader is the shader authoring layer for your engine, framework or content tool. Your team writes shaders in C# using types, structures and attributes. The compiler interprets their interfaces and stages, lowers them to a shared intermediate representation, and generates output for the selected backend.

The central idea is simple: the syntax you write with does not determine the output target. HLSL, GLSL, MSL, SPIR-V and WGSL provide equivalent authoring vocabularies. Choose the one your team knows best, then select SPIR-V or another backend when compiling.

Pipeline
C# with familiar attributes
          ↓
semantic analysis and validation
          ↓
Yotsuba IR
          ↓
SPIR-V · future backends

The three layers#

Yotsuba Shader is organised around three ideas that map to separate projects:

  • Language (YotsubaShader.Language): the attributes and native types you write against. See Shader stages.
  • Intermediate representation (YotsubaShader.IR): a backend-neutral model of functions, storage and interface slots. See Compilation process.
  • Compiler (YotsubaShader.Roslyn, YotsubaShader.Compiler.SpirV): discovery, analysis and SPIR-V emission. See Compilation pipeline.

A shader in one glance#

BasicColorShader.cs
using Microsoft.Xna.Framework;
using YotsubaShader.Language;
using YotsubaShader.HlslSyntax;

public class BasicColorShader
{
    public struct VS_Input
    {
        [POSITION]
        public Vector2 Position;

        [COLOR]
        public Vector4 Color;
    }

    public struct VS_Output
    {
        [SV_Position]
        public Vector4 Position;

        [COLOR]
        public Vector4 Color;
    }

    [ShaderStage(Stage.Vertex)]
    public VS_Output VS(VS_Input input)
    {
        VS_Output output = new VS_Output();

        output.Position = new Vector4(
            input.Position.X,
            input.Position.Y,
            0.0f,
            1.0f
        );

        output.Color = input.Color;

        return output;
    }

    [ShaderStage(Stage.Fragment)]
    [return: SV_Target(0)]
    public Vector4 FS(VS_Output input)
    {
        return input.Color;
    }
}

The example uses HLSL semantics: [POSITION] and [COLOR], plus the built-in [SV_Position]. Numbered [Location(n)] attributes belong to the separate SPIR-V syntax namespace.

Why attributes?#

Attributes make the interface explicit: inputs, outputs, resources, locations, bindings and stages are all declared, never inferred from naming conventions. That is what lets the compiler validate a shader before any GPU is involved.

Copyright © 2026 Yotsuba Shader contributors · Licensing · GitHub