Open-Source Wikis

/

Godot

/

Systems

/

Rendering server

godotengine/godot

Rendering server

Purpose

The rendering server is the engine's largest subsystem — by file count, by lines of code, and by the breadth of its public API. It owns visual state (textures, meshes, materials, lights, environments, instances), schedules culling/visibility, and translates high-level scene draw requests into GPU commands. It supports two architectures in the same source tree: a "RenderingDevice" path that runs on Vulkan, Direct3D 12, and Metal, and a "Compatibility" path that talks directly to OpenGL ES 3.

Directory layout

servers/rendering/
├── rendering_server.{cpp,h}            Public API (~197 KB cpp + ~73 KB h)
├── rendering_server_default.{cpp,h}    Default implementation that owns global storage
├── rendering_server_globals.h          Pointers to the active RasterizerCanvas/Scene/Storage
├── rendering_method.h                  Abstract interface every "renderer" implements
├── rendering_device.{cpp,h}            Vendor-neutral GPU device (~452 KB cpp)
├── rendering_device_driver.{cpp,h}     C++ interface drivers implement (Vulkan/D3D12/Metal)
├── rendering_device_graph.{cpp,h}      DAG-based command scheduler with auto-barriers (~160 KB)
├── rendering_device_commons.{cpp,h}    Shared enums, descriptor structs
├── rendering_device_binds.{cpp,h}      Script-binding-friendly wrappers around RenderingDevice
├── rendering_context_driver.{cpp,h}    Surface/context creation per platform/driver
├── rendering_shader_container.cpp      Shader binary cache + reflection
├── shader_compiler.cpp                 Godot Shader Language → SPIR-V/Metal/HLSL
├── shader_language.cpp                 Godot Shader Language parser/AST/types (~406 KB cpp)
├── shader_preprocessor.cpp             #include / #define handling
├── shader_types.cpp                    Built-in shader uniforms per pass type
├── renderer_canvas_cull.{cpp,h}        2D culling and dispatch (~101 KB cpp)
├── renderer_canvas_render.{cpp,h}      Abstract 2D draw surface implemented per backend
├── renderer_compositor.{cpp,h}         Owns the active rasterizer trio
├── renderer_geometry_instance.{cpp,h}  Per-instance render data
├── renderer_scene_cull.{cpp,h}         3D scene culling (~183 KB cpp)
├── renderer_scene_occlusion_cull.{cpp,h}  Occlusion culling
├── renderer_scene_render.{cpp,h}       Abstract 3D scene render path
├── renderer_viewport.{cpp,h}           Per-viewport state (camera, env, post-process, MSAA, FSR/TAA)
├── rendering_light_culler.{cpp,h}      Light volume culling
├── instance_uniforms.{cpp,h}           Per-instance shader uniforms
├── renderer_rd/                        Renderer running on RenderingDevice
│   ├── forward_clustered/   Forward+ clustered renderer (desktop)
│   ├── forward_mobile/      Mobile forward renderer (tile-friendly)
│   ├── effects/             SSAO, SSIL, SSR, bloom, tonemap, FSR, copy, blur, taa, vrs
│   ├── environment/         Sky, GI (SDFGI/VoxelGI/LightmapGI dispatch), fog, GI probes
│   ├── shaders/             Cluster builder, depth reduce, GI passes, post-process
│   └── storage_rd/          RD-backed mesh/material/texture/light storage
├── storage/                             Backend-agnostic helpers (utility code shared by storages)
├── dummy/                               Headless / `--display-driver headless` no-op renderer
└── environment/                         Default ambient/sky resources

The gles3 "Compatibility" renderer lives in drivers/gles3/ (it predates the RD architecture) and implements the same RendererCompositor / RendererCanvasRender / RendererSceneRender interface set as renderer_rd. See Drivers — Graphics.

Renderer methods

Three rendering methods ship; one is selected per project (rendering/renderer/rendering_method for desktop, rendering/renderer/rendering_method.mobile for mobile, .web for web):

Method Where Backend Use case
Forward+ renderer_rd/forward_clustered/ Vulkan/D3D12/Metal Desktop high-end; clustered forward shading, SDFGI, VoxelGI, SSAO/SSIL/SSR, TAA
Mobile renderer_rd/forward_mobile/ Vulkan/D3D12/Metal Tiled GPUs (mobile, integrated); fewer features for performance
Compatibility drivers/gles3/ OpenGL ES 3 Older hardware, web (WebGL2), low-power mobile

The RD backends share most code (clustered builder, light culler, storage, effects), differing mainly in the lighting/shading pipeline. The Compatibility backend is a separate implementation, but it implements the same interfaces so the high-level RenderingServer API is identical to the consumer.

Public API surface

RenderingServer (rendering_server.h, ~73 KB header) is one of the largest public APIs in Godot. It groups methods into:

  • Texture: texture_2d_create, texture_2d_layered_create, texture_3d_create, texture_proxy_create, texture_replace, plus format/size queries.
  • Mesh / MultiMesh: mesh_create, mesh_add_surface, mesh_set_blend_shape_count, multimesh_create, multimesh_set_buffer.
  • Shader / Material: shader_create, shader_set_code, material_create, material_set_param, material_set_shader.
  • Skeleton: skeleton_create, skeleton_allocate_data, skeleton_bone_set_transform.
  • Light / Reflection / Decal / Lightmap / VoxelGI: factory + setter methods for each.
  • Instance: instance_create, instance_set_base, instance_set_transform, instance_geometry_* (per-instance overrides).
  • Scenario: scenario_create, scenario_set_environment, scenario_set_camera_attributes (a "scenario" is the 3D world a viewport renders).
  • Canvas / CanvasItem / CanvasLayer: 2D draw command lists.
  • Viewport: viewport_create, viewport_set_size, viewport_set_msaa_3d, viewport_set_use_taa, viewport_set_use_hdr_2d, viewport_attach_to_screen.
  • Environment / Sky / Compositor: environment_create, environment_set_sky, environment_set_ssao, compositor_create, compositor_effect_create.
  • Particles: GPU particles infrastructure (particles_create, particles_set_emission_transform, particles_set_amount).
  • GI: voxel_gi_*, lightmap_*, sdfgi_* API.
  • Global shader uniforms: global_shader_parameter_* for cross-shader values.
  • Render frame info / debug: get_rendering_info, get_video_adapter_*, request_frame_drawn_callback.

How a frame flows

sequenceDiagram
    participant Tree as SceneTree
    participant Viewport as Viewport
    participant RS as RenderingServer (WrapMT)
    participant RSD as RenderingServerDefault
    participant Cull as renderer_scene_cull
    participant Method as Forward+ / Mobile / Compat
    participant RD as RenderingDevice / GLES3
    participant GPU

    Tree->>Viewport: draw()
    Viewport->>RS: viewport_draw / canvas_draw
    RS->>RSD: enqueue
    Note over RS,RSD: queued via WrapMT in MT mode
    RSD->>Cull: cull scene + lights + decals + reflection probes
    Cull->>Method: render_scene(...)
    Method->>RD: build framebuffers, bind pipelines, draw
    RD->>GPU: vkCmd* / D3D12 / Metal / GL calls
    GPU-->>RD: frame complete
    RD-->>Method: signal
    Method-->>RSD: frame done
    RSD-->>Viewport: notify draw callbacks

The split is intentional: renderer_scene_cull.cpp is renderer-agnostic and decides what is visible (frustum + occlusion + LOD + lightmap relevance + cluster classification). renderer_rd/forward_clustered/ (or forward_mobile/, or drivers/gles3/) takes that visibility set and turns it into draw calls.

RenderingDevice and the command graph

RenderingDevice is Vulkan-shaped: textures are RD::TextureFormat + RD::TextureView; pipelines are explicit (RD::PipelineRasterizationState, depth/stencil, multisample); barriers are derived automatically by RenderingDeviceGraph.

RenderingDeviceGraph (rendering_device_graph.cpp, ~160 KB) builds a per-frame command DAG so the engine can:

  • Re-order non-dependent commands.
  • Insert pipeline/image-memory barriers only where needed.
  • Schedule async compute on graphics queues that support it.

Both renderer_rd/forward_* and the engine's compute effects (FSR, SSAO, bloom, GI passes) submit through this graph.

Shaders

Godot has its own shader language (an opinionated GLSL dialect with shader_type, render_mode, semantic uniform hints, and shader includes). The pipeline:

  1. Preprocess (shader_preprocessor.cpp) — handles #include directives, #defines, conditional compilation.
  2. Parse (shader_language.cpp, ~406 KB) — produces an AST + symbol table; reports shader_warnings per shader_warnings.cpp.
  3. Compile (shader_compiler.cpp, ~60 KB) — emits SPIR-V (RD path) or GLSL/ESSL (Compatibility path); the SPIR-V is then cross-compiled to Metal MSL or HLSL by the driver.
  4. Cache (rendering_shader_container.cpp) — binary form is cached so re-used shaders skip recompilation.

Built-in shaders for clustered building, GI, post-process, and 2D primitives live in renderer_rd/shaders/. They are converted to C++ string constants by glsl_builders.py at build time.

shader_types.cpp enumerates the built-in uniforms, varyings, and modes available per shader type (canvas_item, spatial, particles, sky, fog).

2D rendering

renderer_canvas_cull.cpp (~101 KB) is the 2D analogue of the 3D culling pipeline:

  • Walks CanvasItem trees, building draw command lists.
  • Resolves Z-ordering and clip rects.
  • Hands batches to the active RendererCanvasRender (RD or GLES3).
  • Implements 2D lights (Light2D) via additive passes against shadow textures.

The 2D path supports custom shaders (canvas_item shader type), 2D shadow occluders (light_occluder_2d), back buffer copy (back_buffer_copy.cpp in scene/2d), and full multi-pass effects through CanvasGroup/SubViewport.

Key abstractions

Abstraction File Role
RenderingServer servers/rendering_server.h Public API
RenderingServerDefault servers/rendering/rendering_server_default.h Owns the active RendererCompositor
RendererCompositor servers/rendering/renderer_compositor.h Owns scene + canvas + storage trio
RendererSceneRender servers/rendering/renderer_scene_render.h Per-backend 3D draw
RendererCanvasRender servers/rendering/renderer_canvas_render.h Per-backend 2D draw
RenderingMethod servers/rendering/rendering_method.h Forward+ / Mobile / Compat method abstraction
RenderingDevice servers/rendering/rendering_device.h Vendor-neutral GPU API
RenderingDeviceGraph servers/rendering/rendering_device_graph.h Command DAG + barrier scheduling
RasterizerScene (per-backend) renderer_rd/forward_*/ and drivers/gles3/rasterizer_scene_gles3.cpp Concrete render-path implementation
ShaderCompiler servers/rendering/shader_compiler.h Godot Shader Language → SPIR-V/GLSL

Integration points

  • Inputs: scene tree calls RenderingServer::* from Viewport, MeshInstance3D, Light3D, Sprite2D, Camera3D, etc., to set up RIDs and update transforms.
  • Outputs: the active RenderingDeviceDriver (Vulkan, D3D12, Metal) executes the GPU commands; or in Compatibility, the GLES3 driver issues GL calls.
  • The compositor effect API (Compositor, CompositorEffect) lets games inject custom RD passes. See scene/resources/compositor.h.

Entry points for modification

  • Adding a new post-process effect → drop a shader into renderer_rd/shaders/effects/, build a wrapper in renderer_rd/effects/, and call it from the renderer's _render_buffers_post_process path. Or, ship it as a CompositorEffect resource so users can attach it from GDScript.
  • Adding a new built-in shader uniform → shader_types.cpp + the relevant shader template.
  • Tweaking culling → renderer_scene_cull.cpp is monolithic but well-commented; profile with the engine's built-in profiler before changes.
  • Adding a new backend → implement RenderingDeviceDriver for the new GPU API and a new RenderingContextDriver. The Vulkan/D3D12/Metal drivers are the templates.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Rendering server – Godot wiki | Factory