{"record":{"id":"fba8722339cce901","repo":"dotnet/wpf","slug":"sr-effect-20shaderusing30registers","errorCode":null,"errorMessage":"SR.Effect_20ShaderUsing30Registers","messagePattern":"SR\\.Effect_20ShaderUsing30Registers","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Effects/ShaderEffect.cs","lineNumber":186,"sourceCode":"            newShader?._shaderBytecodeChanged += OnPixelShaderBytecodeChanged;\n\n            OnPixelShaderBytecodeChanged(PixelShader, null);\n        }\n\n        /// <summary>\n        /// When the PixelShader's bytecode changes to a ps_2_0 shader, verify that registers only\n        /// available in ps_3_0 are not being used.\n        /// </summary>\n        private void OnPixelShaderBytecodeChanged(object sender, EventArgs e)\n        {\n            PixelShader pixelShader = (PixelShader)sender;\n\n            if (pixelShader != null &&\n                pixelShader.ShaderMajorVersion == 2 &&\n                pixelShader.ShaderMinorVersion == 0 &&\n                UsesPS30OnlyRegisters())\n            {\n                throw new InvalidOperationException(SR.Effect_20ShaderUsing30Registers);\n            }\n        }\n\n        private bool UsesPS30OnlyRegisters()\n        {\n            // int and bool registers are ps_3_0 only\n            if (_intCount > 0 || _intRegisters != null ||\n                _boolCount > 0 || _boolRegisters != null)\n            {\n                return true;\n            }\n\n            // float registers 32 or above are ps_3_0 only\n            if (_floatRegisters != null)\n            {\n                for (int i = PS_2_0_FLOAT_REGISTER_LIMIT; i < _floatRegisters.Count; i++)\n                {\n                    if (_floatRegisters[i] != null)","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Effects/ShaderEffect.cs#L168-L204","documentation":"When the PixelShader bytecode changes, ShaderEffect validates that a ps_2_0 shader (major=2, minor=0) is not combined with sampler/register declarations that only exist in ps_3_0 (int and bool registers). Combining them throws InvalidOperationException with Effect_20ShaderUsing30Registers. ps_2_0 hardware/profile has no integer or boolean registers.","triggerScenarios":"Setting PixelShaderCompilerUtil/PixelShader property to a ps_2_0 shader while the effect declares register-based dependencies using int or bool constant types (e.g. via PixelShaderConstantCallback on an int/bool property), or switching an existing effect's shader from ps_3_0 back to ps_2_0 without removing int/bool register usage.","commonSituations":"Downgrading a compiled shader from ps_3_0 to ps_2_0 for wider hardware support while keeping the same C# dependency properties; copying sample code that mixes ps_2_0 bytecode with ps_3_0-only register callbacks.","solutions":["Compile the HLSL with /T ps_3_0 so int/bool registers are supported, and set ShaderRenderMode=SoftwareOnly/HardwareOnly as needed.","Remove int/bool register dependencies (use float registers) if the shader must stay ps_2_0.","Keep shader profile and the effect's declared constant types consistent (ps_2_0: float-only constants)."],"exampleFix":"// before\nfxc /T ps_2_0 effect.hlsl /Fo effect.ps  // effect uses bool registers\n// after\nfxc /T ps_3_0 effect.hlsl /Fo effect.ps","handlingStrategy":"validation","validationCode":"bool usesPS30Only = usesIntOrBoolRegisters; // int/bool constant DPs\nif (pixelShader.ShaderMajorVersion == 2 && pixelShader.ShaderMinorVersion == 0 && usesPS30Only)\n    throw new InvalidOperationException(\"ps_2_0 shader cannot use ps_3_0-only registers\");","typeGuard":"static bool IsPS20(PixelShader ps) => ps != null && ps.ShaderMajorVersion == 2 && ps.ShaderMinorVersion == 0;\nstatic bool IsPS30(PixelShader ps) => ps != null && ps.ShaderMajorVersion == 3 && ps.ShaderMinorVersion == 0;","tryCatchPattern":"try { effect.PixelShader = ps; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ps_2_0\") || ex.Message.Contains(\"registers\"))\n{\n    // recompile shader as ps_3_0 or drop int/bool registers\n}","preventionTips":["Match shader profile to declared constant types: int/bool registers require ps_3_0.","Keep a single source of truth for the shader profile used by an effect.","When downgrading to ps_2_0, remove all int/bool register dependencies first."],"tags":["wpf","shadereffect","pixelshader","ps20","ps30"],"backgroundTag":"incompatible-source-type","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}