{"record":{"id":"f7f40ec311a2f4a3","repo":"stride3d/stride","slug":"width-height-depth-must-be-power-of-2","errorCode":null,"errorMessage":"Width/Height/Depth must be power of 2","messagePattern":"Width/Height/Depth must be power of 2","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Foundation/Graphics/Image.cs","lineNumber":674,"sourceCode":"                mipLevels = 1;\n            }\n            return mipLevels;\n        }\n\n        /// <summary>\n        /// Calculates the number of miplevels for a Texture 2D.\n        /// </summary>\n        /// <param name=\"width\">The width of the texture.</param>\n        /// <param name=\"height\">The height of the texture.</param>\n        /// <param name=\"depth\">The depth of the texture.</param>\n        /// <param name=\"mipLevels\">A <see cref=\"MipMapCount\"/>, set to true to calculates all mipmaps, to false to calculate only 1 miplevel, or > 1 to calculate a specific amount of levels.</param>\n        /// <returns>The number of miplevels.</returns>\n        public static int CalculateMipLevels(int width, int height, int depth, MipMapCount mipLevels)\n        {\n            if (mipLevels > 1)\n            {\n                if (!IsPow2(width) || !IsPow2(height) || !IsPow2(depth))\n                    throw new InvalidOperationException(\"Width/Height/Depth must be power of 2\");\n\n                int maxMips = CountMips(width, height, depth);\n                if (mipLevels > maxMips)\n                    throw new InvalidOperationException($\"MipLevels must be <= {maxMips}\");\n            }\n            else if (mipLevels == 0)\n            {\n                if (!IsPow2(width) || !IsPow2(height) || !IsPow2(depth))\n                    throw new InvalidOperationException(\"Width/Height/Depth must be power of 2\");\n\n                mipLevels = CountMips(width, height, depth);\n            }\n            else\n            {\n                mipLevels = 1;\n            }\n            return mipLevels;\n        }","sourceCodeStart":656,"sourceCodeEnd":692,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Foundation/Graphics/Image.cs#L656-L692","documentation":"The 3D overload of Image.CalculateMipLevels requires Width/Height/Depth to be powers of two when mipLevels > 1, because mip generation for volume textures relies on clean halving. Non-power-of-two dimensions trigger an InvalidOperationException before any mip counting happens.","triggerScenarios":"Calling CalculateMipLevels(width, height, depth, mipLevels) with mipLevels > 1 and any of width, height, depth not a power of two — e.g. 100x100x100 with 4 mips.","commonSituations":"Importing artwork with arbitrary dimensions (e.g. 1920x1080) and requesting a mip chain; volume textures from medical/scientific data with non-PoT sizes; forgetting to pad/resize before mip generation.","solutions":["Resize width/height/depth to the next power of two before computing mip levels","Use mipLevels <= 1 (no chain) if the size cannot be changed","Preprocess the texture offline (e.g. in an asset pipeline step) to power-of-two dimensions"],"exampleFix":"// before\nint mips = Image.CalculateMipLevels(100, 100, 100, 4);\n// after\nint size = 128; // next pow2\nint mips = Image.CalculateMipLevels(size, size, size, 4);","handlingStrategy":"validation","validationCode":"bool IsPow2(int v) => v > 0 && (v & (v - 1)) == 0;\nif (mipLevels > 1 && !(IsPow2(w) && IsPow2(h) && IsPow2(d)))\n    // resize to next power of two first","typeGuard":"bool CanGenerateVolumeMips(int w, int h, int d, int mips) => mips <= 1 || (IsPow2(w) && IsPow2(h) && IsPow2(d));","tryCatchPattern":"try { mips = Image.CalculateMipLevels(w, h, d, count); }\ncatch (InvalidOperationException) { w = NextPow2(w); h = NextPow2(h); d = NextPow2(d); mips = Image.CalculateMipLevels(w, h, d, count); }","preventionTips":["Enforce power-of-two texture sizes in the asset pipeline for 3D/volume textures","Add a NextPow2 helper and apply it before mip generation"],"tags":["csharp","stride","graphics","mipmap","power-of-two"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}