OpenRA/OpenRA · error · InvalidDataException
Frame buffer size ({size.Width}x{size.Height}) must be a pow
Error message
Frame buffer size ({size.Width}x{size.Height}) must be a power of two What it means
Thrown by the FrameBuffer constructor when either size.Width or size.Height is not a power of two (Exts.IsPowerOf2). The legacy GL framebuffer path requires power-of-two dimensions for the color texture and depth renderbuffer. InvalidDataException at construction time.
Source
Thrown at OpenRA.Platforms.Default/FrameBuffer.cs:33
using OpenRA.Primitives;
namespace OpenRA.Platforms.Default
{
sealed class FrameBuffer : ThreadAffine, IFrameBuffer
{
readonly ITexture texture;
readonly Size size;
readonly Color clearColor;
uint framebuffer, depth;
bool disposed;
bool scissored;
public FrameBuffer(Size size, ITextureInternal texture, Color clearColor)
{
this.size = size;
this.clearColor = clearColor;
if (!Exts.IsPowerOf2(size.Width) || !Exts.IsPowerOf2(size.Height))
throw new InvalidDataException($"Frame buffer size ({size.Width}x{size.Height}) must be a power of two");
OpenGL.glGenFramebuffers(1, out framebuffer);
OpenGL.CheckGLError();
OpenGL.glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, framebuffer);
OpenGL.CheckGLError();
// Color
this.texture = texture;
texture.SetEmpty(size.Width, size.Height);
OpenGL.glFramebufferTexture2D(OpenGL.GL_FRAMEBUFFER, OpenGL.GL_COLOR_ATTACHMENT0, OpenGL.GL_TEXTURE_2D, texture.ID, 0);
OpenGL.CheckGLError();
// Depth
OpenGL.glGenRenderbuffers(1, out depth);
OpenGL.CheckGLError();
OpenGL.glBindRenderbuffer(OpenGL.GL_RENDERBUFFER, depth);
OpenGL.CheckGLError();View on GitHub (pinned to a520984d91)
Solutions
- Pass power-of-two dimensions (e.g. 1024, 2048) to the FrameBuffer constructor.
- Clamp the requested size up to the next power of two before constructing.
- Use a renderer path that supports NPOT textures if the GPU allows it.
- Check the caller supplying the Size (window/viewport setup) and round it to PoT.
Example fix
// before
var fb = new FrameBuffer(new Size(width, height), texture, clearColor);
// after - round up to next power of two
int NextPoT(int v) { var p = 1; while (p < v) p <<= 1; return p; }
var fb = new FrameBuffer(new Size(NextPoT(width), NextPoT(height)), texture, clearColor); Defensive patterns
Strategy: validation
Validate before calling
if (!Exts.IsPowerOf2(size.Width) || !Exts.IsPowerOf2(size.Height))
throw new InvalidDataException(
$"Frame buffer size ({size.Width}x{size.Height}) must be a power of two."); Type guard
static bool IsPoTSize(Size s) => Exts.IsPowerOf2(s.Width) && Exts.IsPowerOf2(s.Height);
Prevention
- Round requested framebuffer dimensions up to the next power of two.
- Avoid arbitrary display-resolution render targets on the PoT path.
- Centralize PoT rounding in the renderer's buffer-allocation helper.
When it happens
Trigger: Constructing a FrameBuffer with a Size whose width or height is e.g. 1920, 1080, 1366 — any non-PoT value — during renderer/window/sprite-buffer setup.
Common situations: A non-power-of-two display resolution or render target being passed in; a high-DPI/retina scale producing non-PoT backbuffer sizes; custom render targets with arbitrary dimensions; running on the default (non-NPOT) platform renderer.
Related errors
- OpenGL Error: See graphics.log for details.
- Failed to initialize an OpenGL debug message callback.
- Failed to initialize OpenGL. See graphics.log for details.
- Failed to initialize low-level OpenGL bindings. GPU informat
- OpenGL Version Error: See graphics.log for details.
AI-assisted analysis of OpenRA/OpenRA@a520984d91 (2026-08-13).
Data as JSON: /api/errors/2f117eaf6e854fb0.
Report an issue: GitHub.