Xna HLSL:在编译时强制执行常量寄存器限制

Xna HLSL:在编译时强制执行常量寄存器限制,xna,shader,hlsl,vertex-shader,Xna,Shader,Hlsl,Vertex Shader,在HLSL中,有没有办法限制编译器使用的常量寄存器的数量 具体地说,如果我有以下情况: float4 foobar[300]; 在vs_2_0顶点着色器中,编译器将愉快地生成具有256个以上常量寄存器的效果。但是2.0顶点着色器只能保证访问256个常量寄存器,所以当我尝试使用该效果时,它在运行时以一种模糊且依赖于GPU的方式失败。我宁愿它在编译时失败 这个问题尤其令人恼火,因为编译器本身在后台分配常量寄存器,而不是我要求的寄存器。我得检查一下总成,看看是否超过了限度 理想情况下,我希望在HLS

在HLSL中,有没有办法限制编译器使用的常量寄存器的数量

具体地说,如果我有以下情况:

float4 foobar[300];
在vs_2_0顶点着色器中,编译器将愉快地生成具有256个以上常量寄存器的效果。但是2.0顶点着色器只能保证访问256个常量寄存器,所以当我尝试使用该效果时,它在运行时以一种模糊且依赖于GPU的方式失败。我宁愿它在编译时失败

这个问题尤其令人恼火,因为编译器本身在后台分配常量寄存器,而不是我要求的寄存器。我得检查一下总成,看看是否超过了限度


理想情况下,我希望在HLSL中这样做(我使用的是XNA内容管道),但是如果有一个标志可以传递给编译器,这也会很有趣。

基于Stringer Bell对反汇编方法的指出,我已经启动了一个小的构建后实用程序来解析和检查效果。请注意,这不是很漂亮。它是为XNA 3.1设计的,需要来自的
ServiceContainer
GraphicsDeviceService
类。在命令行上传递内容目录路径,不带尾随斜杠

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;
    }
}
类程序
{
const int maxRegisters=256;//适用于VS 2.0,其他不多
静态int-retval=0;
静态字符串根;
静态ContentManager内容;
静态无效检查文件(字符串路径)
{
字符串名称=path.Substring(root.Length+1,path.Length-(root.Length+1)-@“.xnb.Length);
效应;
试试{effect=content.Load(name);}
catch{return;}//可能不是效果
string effectSource=effect.discompose(false);
int highest=-1;//分配的最高寄存器
var matches=Regex.matches(effectSource,@“c([0-9]+)”);//快速且脏
foreach(匹配中的匹配)
{
int register=Int32.Parse(match.Groups[1].ToString());
如果(寄存器>最高值)
最高=寄存器;
}
var parameters=Regex.Matches(effectSource,@“^*/*[a-zA-Z_0-9]++c(+[0-9]+)+([0-9]+”,RegexOptions.Multiline);
foreach(参数匹配)
{
int register=Int32.Parse(match.Groups[1].ToString())+Int32.Parse(match.Groups[2].ToString())-1;
如果(寄存器>最高值)
最高=寄存器;
}
如果(最高+1>最大寄存器)
{
WriteLine(“错误:着色器\”“+name+“\”使用“+(最高+1).ToString()+”常量寄存器,太多了!”);
retval=1;
}
其他的
{
WriteLine(“着色器\”+name+“\”使用“+(最高+1).ToString()+”常量寄存器(OK)”;
}
}
静态无效检查目录(字符串路径)
{
尝试
{
foreach(目录.GetFiles(路径@“*.xnb”)中的字符串文件)
检查文件(文件);
foreach(Directory.GetDirectories(path)中的字符串dir)
检查目录(dir);
}
catch{return;}//不在乎
}
静态int Main(字符串[]args)
{
root=args[0];
Form Form=new Form();//用于创建图形设备的虚拟表单
GraphicsDeviceService gds=GraphicsDeviceService.AddRef(form.Handle,
form.ClientSize.Width、form.ClientSize.Height);
ServiceContainer服务=新ServiceContainer();
服务。添加服务(gds);
content=newcontentmanager(服务,根目录);
检查目录(根目录);
返回返回;
}
}

基于Stringer Bell指出的反汇编方法,我创建了一个小的构建后实用程序来解析和检查效果。请注意,这不是很漂亮。它是为XNA 3.1设计的,需要来自的
ServiceContainer
GraphicsDeviceService
类。在命令行上传递内容目录路径,不带尾随斜杠

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;
    }
}
类程序
{
const int maxRegisters=256;//适用于VS 2.0,其他不多
静态int-retval=0;
静态字符串根;
静态ContentManager内容;
静态无效检查文件(字符串路径)
{
字符串名称=path.Substring(root.Length+1,path.Length-(root.Length+1)-@“.xnb.Length);
效应;
试试{effect=content.Load(name);}
catch{return;}//可能不是效果
string effectSource=effect.discompose(false);
int highest=-1;//分配的最高寄存器
var matches=Regex.matches(effectSource,@“c([0-9]+)”);//快速且脏
foreach(匹配中的匹配)
{
int register=Int32.Parse(match.Groups[1].ToString());
如果(寄存器>最高值)
最高=寄存器;
}
var parameters=Regex.Matches(effectSource,@“^*/*[a-zA-Z_0-9]++c(+[0-9]+)+([0-9]+”,RegexOptions.Multiline);
foreach(参数匹配)
{
int register=Int32.Parse(match.Groups[1].ToString())+Int32.Parse(match.Groups[2].ToString())-1;
如果(寄存器>最高值)
最高=寄存器;
}
如果(最高+1>最大寄存器)
{
WriteLine(“错误:着色器\”“+name+“\”使用“+(最高+1).ToString()+”常量寄存器,太多了!”);
retval=1;
}
其他的
{
WriteLine(“着色器\”+name+“\”使用“+(最高+1).ToString()+”常量寄存器(OK)”;
}
}
静态无效检查目录(字符串路径)
{
尝试
{
foreach(目录.GetFiles(路径@“*.xnb”)中的字符串文件)
检查文件(文件);
foreach(Directory.GetDirectories(path)中的字符串dir)
检查目录(目录)