2010-05-19 6 views
1

HLSL에서 컴파일러가 사용하는 상수 레지스터의 수를 제한하는 방법이 있습니까? I는 같은 있다면HLSL : 컴파일 타임에 상수 레지스터 제한 적용

구체적로서, vs_2_0 정점 셰이더

float4 foobar[300]; 

를 컴파일러 즐겁게 256 개 상수 레지스터와 효과를 생성한다. 하지만 2.0 버텍스 쉐이더는 256 개의 상수 레지스터에 대한 액세스 만 보장되므로이 효과를 사용하려고하면 런타임시 애매하고 GPU에 의존하는 방식으로 실패합니다. 나는 오히려 그것을 컴파일 시간에 실패하게 만들 것이다.

이 문제는 컴파일러 자체가 내가 궁금해하는 것들의 위에 장면의 배후에서 상수 레지스터를 할당하기 때문에 특히 성가신 일입니다. 나는 한계를 넘었는지 확인하기 위해 어셈블리를 점검해야한다.

HLSL (XNA 콘텐츠 파이프 라인을 사용하고 있습니다)에서이 작업을 수행하고 싶습니다.하지만 흥미로운 컴파일러에 전달할 수있는 플래그가있는 것이 이상적입니다.

+0

좋은 질문입니다. 나는 DirectX 개발자들이 거기에 매달려 있기 때문에 http://forums.xna.com/forums/27.aspx에 게시 할 것입니다. – Stringer

+0

감사합니다. Stringer Bell. 제안한대로 XNA 포럼에 게시했습니다. http://forums.xna.com/forums/p/53856/326864.aspx –

+0

또한 HLSL이나 컴파일러에서 수행 할 방법이 없다면 컴파일 된 셰이더가 프로그래밍 방식으로 사용하는 상수 레지스터의 수를 계산하는 방법은 무엇입니까? (이상적으로 XNA 사용) –

답변

1

Stringer Bell이 Disassemble 메서드를 지적했기 때문에 구문 분석 및 효과 확인을 위해 작은 빌드 빌드 유틸리티를 작성했습니다. 이것이 아주 예쁘지 않다는 경고를 받으십시오. XNA 3.1 용으로 설계되었으며의 ServiceContainerGraphicsDeviceService 클래스가 필요합니다. 슬래시가없는 명령 줄에서 내용 디렉토리 경로를 전달하십시오.

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; 
    } 
} 
관련 문제