Distance based optimization material instructions. Switching the set of instructions in the material during rendering.

I’m trying to create a material that will be optimized as the camera moves away from the surface. In the near material used large sets of instructions, such as parallax. When using the IF node, the material editor generates the error: [SM5] (Node If) Failed to compile AGreaterThanB input. Nod SWITCH not suitable, because is static. I also know that I can use LODs, but I want to do this in the material, because in my project, LODs is not convenient to use.

Is it possible to implement such a material, as in the attached picture?
Is it possible to dynamically control the shader’s instruction kit during rendering?
Please tell me what methods to implement my idea without LODs materials sets.

Once the shader code is compiled its instruction count remains constant. It is irrelevant what kind of data is running through it, every instruction will be executed, even if the end result doesn’t even change a pixel in the final image. This is due to the architecture of the GPU: Single instruction - multiple data (SIMD: Single instruction, multiple data - Wikipedia) One program fed by different data for each pixel.
Optimization mostly means the preparation of the data before it gets onto the video card, so yes, LOD, texture atlases, drawcall reduction and so on. (See: Performance and Profiling | Unreal Engine Documentation)

Thanks for the info about SIMD. Thanks to this information, I found the following topic: https://www.gamedev.net/forums/topic/602402-hlsl-dynamic-branching-performance/

As I understand it, this limitation is in material editor due to the complexity of automatic optimization, but this is possible when creating a custom shader. But also with a thoughtful approach. Attached the text from the forum, because information may be useful to other users:

<< In my shaders I , often, use if() and for() is there any “rules” to make dynamic branching faster?>>

Well first of all, using an “if” or a “for” does not automatically mean you’re getting a branch in your shader. The compiler can flatten branches and unroll loops if it’s possible to do so. You should check the shader assembly to verify. You can also use attributes to force the compiler to flatten or unroll.

Anyway the number 1 rule for dynamic branching is coherence. You need lots of adjacent pixels (usually within a 32x32 or 64x64 block) to take the same branch, otherwise you end up with all of those pixels taking both branches and doing wasted work. So if you’re trying to use dynamic branching as an optimization, only do it for things where the branch will be the same for large portions of the screen. Also it helps to only use a branch to try to skip large sections of code as opposed to smaller ones, since having a branch adds some fixed overhead itself.