- From: Kai Ninomiya <kainino@google.com>
- Date: Tue, 27 Nov 2018 15:03:47 -0800
- To: "Myles C. Maxfield" <mmaxfield@apple.com>
- Cc: public-gpu <public-gpu@w3.org>
- Message-ID: <CANxMeyCFkEHM1VjoaQgTpgw-NC3NpWOjUJkGWHyU4P7R=3E1KA@mail.gmail.com>
Hey Myles, thanks for this report! Great to see things laid out.
> Many files in the corpus use HLSL’s syntax for sampler literals, but
those aren’t supported in SPIR-V, so I think we can safely ignore those. I
don’t know what the SPIR-V Cross guys are doing about that.
Just to clarify, by SPIR-V Cross did you mean DXC
<https://github.com/Microsoft/DirectXShaderCompiler/blob/master/docs/SPIR-V.rst#samplers>?
SPIRV-Cross doesn't compile HLSL to SPIR-V, it compiles SPIR-V to HLSL.
On Tue, Nov 27, 2018 at 2:30 PM Myles C. Maxfield <mmaxfield@apple.com>
wrote:
> Over the past few days, I’ve collected a large corpus of HLSL files so we
> can determine what we need to do to be source-compatible with existing HLSL
> source.
>
> *The Corpus*
>
> I wrote a GitHub crawler which looked for repositories that had many HLSL
> files in them. I looked over the results of this crawler and hand-picked a
> few repositories that are from respectable sources. In total, we ended up
> with 2099 HLSL files.
>
> The list of repositories:
>
> - Microsoft/DirectX-Graphics-Samples
> - vvvv/vvvv-sdk
> - Of limited use, because most of the source is written in another
> language (Effects) which includes HLSL snippets. GitHub classifies this as
> HLSL.
> - Unity-Technologies/ScriptableRenderPipeline
> - Of limited use, because most of the source is written in another
> language (Shaderlab) which includes HLSL snippets. GitHub classifies this
> as HLSL.
> - Microsoft/Windows-universal-samples
> - OGRECave/ogre
> - EpicGames/UnrealEngine
> - Of limited use, because most of the source is written in another
> language (Unreal Shader Format) which includes HLSL snippets. GitHub
> classifies this as HLSL.
> - ConfettiFX/The-Forge
> - AtomicGameEngine/AtomicGameEngine
> - NVIDIAGameWorks/D3DSamples
> - EpicGames/UnrealTournament
> - Of limited use, because most of the source is written in another
> language (Unreal Shader Format) which includes HLSL snippets. GitHub
> classifies this as HLSL.
> - urho3d/Urho3D
> - NVIDIAGameWorks/HairWorks
> - NVIDIAGameWorks/WaveWorks
> - Of limited use, because most of the source is written in another
> language (Effects) which includes HLSL snippets. GitHub classifies this as
> HLSL.
> - NVIDIAGameWorks/FleX
> - Unity-Technologies/PostProcessing
> - Of limited use, because most of the source is written in another
> language (Shaderlab) which includes HLSL snippets. GitHub classifies this
> as HLSL.
> - NVIDIAGameWorks/Falcor
> - NVIDIAGameWorks/FaceWorks
> - NVIDIAGameWorks/HBAOPlus
> - GPUOpen-LibrariesAndSDKs/GPUParticles11
> - NVIDIAGameWorks/VolumetricLighting
> - GPUOpen-Effects/ShadowFX
> - GPUOpen-LibrariesAndSDKs/LiquidVR
> - NVIDIAGameWorks/NvCloth
> - GPUOpen-Effects/DepthOfFieldFX
> - NVIDIAGameWorks/PhysX-3.4
> - GPUOpen-Effects/GeometryFX
> - GPUOpen-LibrariesAndSDKs/TiledLighting11
> - NVIDIAGameWorks/Flow
> - GPUOpen-LibrariesAndSDKs/ForwardPlus11
> - Microsoft/Win2D
> - GPUOpen-LibrariesAndSDKs/SSAA11
> - Microsoft/Win2D-Samples
> - PixarAnimationStudios/OpenSubdiv
>
> We could potentially figure out how to compile Effects, Shaderlab and
> Unreal Shader Format to HLSL (because that’s what their engines do). If we
> did this, we could grow the repository by 13% + 8% + 15% (respectively) =
> 36%. I didn’t want to get bogged down doing this, though.
>
> *Preprocessor*
>
> HLSL Source files make heavy use of the preprocessor. Each file includes
> an average of 9.61 uses of the preprocessor (lines that begin with “#”) and
> the preprocessor is used on average every 11.68 lines.
>
>
> As you can see above, most of the users of the preprocessor are not to
> include files, but are instead to enable / disable features. Therefore,
> this is a situation where compatibility with existing HLSL source is
> directly in conflict with simplicity of the language.
>
> I proceeded by running the corpus through the Microsoft HLSL preprocessor,
> and investigated the preprocessed files. My analysis is just based on the
> parsing stage of the language, not name resolution or type checking.
> Out-of-the-box, we parse 5.9% of the corpus.
>
> *Language Features*
>
> From investigating the source, I found some language features that HLSL
> depends on.
>
> In MSL, if you want to pass some data to your shader, you make a struct,
> and pass a reference to that struct as an argument of the main function.
> Then, in the main function, you reference the data by saying
> theReference.field. This approach is possible in HLSL, but there’s another
> more common way to do it. Instead of making a struct, you make a “cbuffer”
> which lists a set of fields, but those fields are treated as global
> variables. The cbuffer is given a “semantic” so the API can attach memory
> to back the cbuffer.
>
> cbuffer Camera : register(b0) // The API assigns memory to this block by
> using the “b0” handle
> {
> float4x4 viewProjection;
> float4x4 projectionInv;
> float3 viewPos;
> };
>
> Output main() {
> output.foo = viewProjection; // viewProjection, projectionInv, and
> viewPos are in the global scope.
> return output;
> }
>
> About 1/3 of the files in the corpus use cbuffers.
>
> HLSL has two flavors of global variables:
>
> 1. Resources, like RWTexture2D<float2> dstTexture : register(u0);.
> These work just like entry point parameters, except they are in the global
> scope and therefore can be accessed from any function, without passing
> around a pointer to them.
> 2. Literal data, like static const float convolutionWeights[] = {1, 2,
> 3};.
>
>
> About 1/5 of the files in the corpus use global variables.
>
> HLSL supports default arguments in function parameters and cbuffers, so
> you can say void foo(int x = 3);. I would imagine specifying this would
> be tricky because we have to mention which variables and functions the
> initial value can refer to.
>
> Many files in the corpus use HLSL’s syntax for sampler literals, but those
> aren’t supported in SPIR-V, so I think we can safely ignore those. I don’t
> know what the SPIR-V Cross guys are doing about that.
>
> *New Syntax*
>
> There are lots of changes to the syntax of the language that shouldn’t
> have much of an effect on the language itself, but are required if we want
> to claim compatibility with lots of HLSL sources.
>
>
> - Removing the entry point keywords (vertex, fragment, compute) is a
> requirement for any shader to compile. Instead, we should require that
> compilation of a WHLSL file state which function names are the entry points.
> - It appears that HLSL allows any arbitrary semantic for stage in/out
> parameters. Around 30% of the corpus uses a semantic that WHLSL doesn’t
> currently accept.
> - Some functions in the HLSL standard library use
> member-function-syntax, like texture.Sample(sampler, location) instead
> of Sample(texture, sampler, location).
> - There are a whole collection of variable modifiers that HLSL sources
> use that WHLSL doesn’t accept. E.g. row_major float4x4 mvpMatrix;
> - HLSL has a few function modifiers like [ RootSignature(…stuff goes
> here…) ] void foo(…) { … } that are irrelevant for WebGPU. This
> includes information about the D3D root signature, but also things like how
> geometry shaders and tessellation work, which WebGPU doesn’t have.
> - HLSL arrays put the brackets after the variable name, like float
> myArray[40];
> - Arrays and structs can be initialized using brackets, like float
> myArray[3] = { 1.0, 2.0, 3.0 };
> - HLSL has some hints about how the compiler should treat branches and
> loops. They look like [ unroll ] for (…) and [ branch ] if ( …). I
> don’t think these have semantic meaning so we can probably just swallow
> them.
> - HLSL uses C-style casts instead of C++-style casts. So, we need to
> support (float)x instead of float(x).
> - HLSL accepts float literals with exponents, like 1e-3.
> - Functions can be forward-declared in HLSL.
>
>
> After doing all that, we get up to around 90% compatibility with parsing
> (not resolving names nor type checking) the HLSL corpus. The biggest wins
> are member-function syntax, allowing every semantic name, C-style casting,
> and C-style array syntax.
>
> —Myles
>
Attachments
- image/jpeg attachment: Screen_Shot_2018-11-13_at_1.03.53_PM.jpeg
- image/jpeg attachment: 02-Screen_Shot_2018-11-13_at_1.03.53_PM.jpeg
- application/pkcs7-signature attachment: S/MIME Cryptographic Signature
Received on Tuesday, 27 November 2018 23:04:25 UTC