[LLVMdev] [GSoC] "Microsoft Direct3D shader bytecode backend" proposal

Jim Grosbach grosbach at apple.com
Tue Mar 29 10:09:39 PDT 2011


On Mar 29, 2011, at 9:02 AM, Charles Davis wrote:

> On 3/29/11 5:14 AM, Justin Holewinski wrote:
>> On Mon, Mar 28, 2011 at 9:22 PM, Charles Davis <cdavis at mymail.mines.edu
>> <mailto:cdavis at mymail.mines.edu>> wrote:
>> 
>>    Here's the other of my proposals for this year's Google Summer of Code.
>>    (The first is on cfe-dev.) It was suggested to me by Dan Kegel (from the
>>    Wine project, they really want this).
>> 
>>    Title: Microsoft Direct3D shader bytecode backend
>> 
>>    Abstract:
>> 
>>    There is a distinct lack of open-source frameworks for compiling HLSL,
>>    the shader language used by Direct3D, into bytecode that D3D can
>>    understand. Currently, the only such framework is Ryan Gordon's
>>    MojoShader, whose HLSL compiler component is still under heavy
>>    development. By utilizing LLVM, it may be possible to generate
>>    high-performance shader code from HLSL, just as Apple is known to do for
>>    GLSL. The first step is a backend to generate D3D bytecode from LLVM IR.
>> 
>>    Content:
>> 
>>    1. Proposal
>> 
>>    Currently, there are very few open-source frameworks for compiling
>>    High-Level Shader Language (HLSL) into shader bytecode that can be
>>    understood by Direct3D, a popular interface to 3D hardware in games.
>>    This is because Microsoft provides its own interface in its D3DX (and
>>    underlying D3DCompiler) DLLs. Most games therefore end up using D3DX to
>>    compile their Direct3D shaders.
>> 
>>    Microsoft seems to have paid no attention to optimization of the
>>    resulting shader code, though. With LLVM, we can do better.
>> 
>> 
>> Do you have any sources for this?  In my experience, fxc is able to do
>> some clever tricks such as replacing if-then-else conditions with
>> predicated instructions and swizzles.
> I heard rumors that drivers tend not to like highly optimized bytecode
> input. But that seems to count against optimization. I could take that
> part out.
>> 
>> 
>> 
>>    By using LLVM's optimizers, programs can potentially generate
>>    high-performance shader code that works well on the platform on which
>>    they are running. In addition, an open-source implementation would allow
>>    the compiler to be embedded in many different applications--not the
>>    least of which is Wine, which is in desperate need of a working shader
>>    compiler.
>> 
>> 
>> I'm a bit confused how Wine would take advantage of a Direct3D bytecode
>> compiler.  Would they not want to re-compile Direct3D bytecode (most
>> often shipped with games in binary form instead of HLSL source) to
>> something an OpenGL implementation on *nix could handle?
> They already do that. What they want right now (among other things) is a
> D3DCompiler_*.dll implementation (see http://wiki.winehq.org/HLSLCompiler ).
>> 
>> 
>> 
>>    The first step to this HLSL compiler is an LLVM backend for generating
>>    D3D shader bytecode from LLVM IR. Therefore, I intend to implement such
>>    a backend. Because implementing a full backend is a daunting task, I
>>    intend to implement just enough to get simple examples working with
>>    Wine's Direct3D implementation.
>> 
>> 
>> Could you be a bit more specific on your goals?  A few quick questions
>> that come to mind are:
>> 
>> 1. What shader models will you aim to support?
> SM1-3. SM4 was a huge break from SM3 (so I've gathered from reading Wine
> source; all the opcodes seem to be different), so I'll do that later.
>> 2. What types of shared will you aim to support?  e.g. vertex, pixel,
>> geometry, hull
> Since I'm only doing up to SM3, vertex and pixel shaders only.
>> 3. How do you propose to handle vertex buffer semantics?  e.g.
>> POSITION0, TEXCOORD0, NORMAL, etc.
> I can think of several ways:
> 
> - Make the frontend declare special symbols, and handle these symbols
> specially in the backend
> - Decorate the struct members with metadata
> 
> I'm leaning towards the latter one.

Does this mean that the metadata would be required for correctness? If so, metadata is not a good choice, as being able to strip it and still get correct output is an LLVM constrain. If it would just result in suboptimal, but still correct, results, then it's a fine choice. See, for example, TBAA.

-Jim

>> 
>> Perhaps a simple example would be nice, showing a very simple LLVM IR
>> input and the (proposed) bytecode output.
> How about this (this is from
> http://www.neatware.com/lbstudio/web/hlsl.html)?
> 
> struct a2v {
>  float4 position : POSITION;
> };
> 
> struct v2p {
>  float4 position : POSITION;
> };
> 
> void main(in a2v IN, out v2p OUT, uniform float4x4 ModelViewMatrix) {
>  OUT.position = mul(IN.position, ModelViewMatrix);
> }
> 
> This would generate something like this (assuming I took the metadata
> route):
> 
> %struct.a2v = { <4 x float> !0 }
> %struct.v2p = { <4 x float> !0 }
> 
> !0 = metadata !{ <something that indicates this is a position attribute> }
> 
> define void @main(%struct.a2v* %IN, %struct.v2p* %OUT, [4 x <4 x float>]
> %ModelViewMatrix) {
>  %OUT.Position = getelementptr %struct.v2p* %OUT, i32 0, i32 0
>  %IN.Position = getelementptr %struct.a2v* %IN, i32 0, i32 0
>  %0 = load <4 x float>* %IN.Position
>  # Note the intrinsic for matrix multiplies
>  %1 = call <4 x float> @llvm.d3d.mul.float4(<4 x float>%0, [4 x <4 x
> float>] %ModelViewMatrix)
>  store <4 x float> %1, <4 x float>* %OUT.Position
> }
> 
> and should generate assembly to the effect of:
> 
> vs_1_1
> dcl_position v0
> m4x4 oPos, v0, c0
> mov oD0, c4
> 
> Thanks for your input.
> 
> Chip
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list