HLSL: forced compilation of case-sensitive constraints

In HLSL, is there a way to limit the number of constant registers that the compiler uses?

In particular, if I have something like:

float4 foobar[300];

In the vs_2_0 vertex shader, the compiler will generate an effect with more than 256 constant registers. But the Ver.2 Vertex Shader is only guaranteed to access 256 constant registers, so when I try to use the effect, it does not work in ambiguity mode and depends on the GPU at runtime. I would rather refuse at compile time.

This problem is particularly annoying because the compiler itself allocates constant registers behind the scenes on top of the ones I ask. I have to check the assembly to make sure that I have exceeded the limit.

Ideally, I would like to do this in HLSL (I use the XNA content pipeline), but if there is a flag that can be passed to the compiler, it will also be interesting.

+1
source share
1 answer

Based on Stringer Bell specifying the Disassemble method, I hacked a small utility after assembly to analyze and test the effect. Be warned that it is not very beautiful. It is designed for XNA 3.1 and requires classes to ServiceContainerand GraphicsDeviceServicefrom the XNA image of WinForms . Skip the path of the content directory on the command line without a trailing slash.

class Program
{
    const int maxRegisters = 256; // Sutiable for VS 2.0, not much else
    static int retval = 0;
    static string root;
    static ContentManager content;

    static void CheckFile(string path)
    {
        string name = path.Substring(root.Length+1, path.Length - (root.Length+1) - @".xnb".Length);
        Effect effect;
        try { effect = content.Load<Effect>(name); }
        catch { return; } // probably not an Effect
        string effectSource = effect.Disassemble(false);

        int highest = -1; // highest register allocated

        var matches = Regex.Matches(effectSource, @" c([0-9]+)"); // quick and dirty
        foreach(Match match in matches)
        {
            int register = Int32.Parse(match.Groups[1].ToString());
            if(register > highest)
                highest = register;
        }

        var parameters = Regex.Matches(effectSource, @"^ *// *[a-zA-Z_0-9]+ +c([0-9]+) +([0-9]+)", RegexOptions.Multiline);
        foreach(Match match in parameters)
        {
            int register = Int32.Parse(match.Groups[1].ToString()) + Int32.Parse(match.Groups[2].ToString()) - 1;
            if(register > highest)
                highest = register;
        }

        if(highest+1 > maxRegisters)
        {
            Console.WriteLine("Error: Shader \"" + name + "\" uses " + (highest+1).ToString() + " constant registers, which is TOO MANY!");
            retval = 1;
        }
        else
        {
            Console.WriteLine("Shader \"" + name + "\" uses " + (highest+1).ToString() + " constant registers (OK)");
        }
    }

    static void CheckDirectory(string path)
    {
        try
        {
            foreach(string file in Directory.GetFiles(path, @"*.xnb"))
                CheckFile(file);
            foreach(string dir in Directory.GetDirectories(path))
                CheckDirectory(dir);
        }
        catch { return; } // Don't care
    }

    static int Main(string[] args)
    {
        root = args[0];

        Form form = new Form(); // Dummy form for creating a graphics device
        GraphicsDeviceService gds = GraphicsDeviceService.AddRef(form.Handle,
                form.ClientSize.Width, form.ClientSize.Height);

        ServiceContainer services = new ServiceContainer();
        services.AddService<IGraphicsDeviceService>(gds);
        content = new ContentManager(services, root);

        CheckDirectory(root);

        return retval;
    }
}
+1
source

Source: https://habr.com/ru/post/1762775/


All Articles