Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call for input on HLSL -> SPIR-V translation #200

Closed
johnkslang opened this issue Mar 13, 2016 · 52 comments
Closed

Call for input on HLSL -> SPIR-V translation #200

johnkslang opened this issue Mar 13, 2016 · 52 comments

Comments

@johnkslang
Copy link
Member

There have been multiple requests for HLSL -> SPIR-V translation. Given the likelihood of multiple ways of doing this and multiple parties interested in it, this is a place to discuss.

One possible way of doing it is introduced in the hlsl-frontend branch. If this method looks good, it needs to be finished by completing all the HLSL grammar details, translating it into the same AST that GLSL is translated into. The grammar -> AST does not have much functionality yet, but is otherwise set up with relatively complete infrastructure throughout glslang -> SPIR-V.

See the commits at https://github.com/KhronosGroup/glslang/commits/hlsl-frontend, summarized below. The initial commits are less HLSL-specific and might be good steps to take regardless.

  1. Generalize GLSL's "main" to a settable entry point name.
  2. Support multiple source languages, adding HLSL as an option.
  3. Refactor TParseContext into 3 level inheritance. [ This is needed anyway. ]
  4. HLSL: Plumb in HLSL parse context and keywords, and most basic HLSL parser and test.
  5. ... N. < series of incremental functionality to the HLSL parser >
@johnkslang
Copy link
Member Author

This picture shows the basic architectural plumbing of the new branch:

hlsl.pdf

@AWoloszyn
Copy link
Contributor

Currently the architecture of glslang prevents 2 libraries in the same process from using glslang at the same time. (Each would have to be aware of the other in order to safely call Initialize/Finalize Process).

This can cause enormously difficult to track down bugs in any programs that include, for example, glslang and shaderc.

Can we prevent the hlsl backend from falling into the same pit. Specifically

// A single global usable by all threads, by all versions, by all languages.

furthers this problem.

Potential Solutions:
1)

static const std::unordered_map<const char*, glslang::EHlslTokenClass, str_hash, str_eq> KeywordMap =
{
 {"static", EHTokStatic},
...
};

Which would initialize the KeywordMap only once, and then only destroy it at program exit. This way programs never have to deal with it.

  1. Alternatively since there are only on the order of 100 entries into each map, something like
struct Keyword {
  const char* name;
  EHlslTokenClass token;
}
const Keyword keywords[] = {
 {"bool", EHTokBool}, 
...
};

May be preferable given that it has zero initialization cost and (this is just a gut feeling, would need to measure) the performance difference of doing binary search on a 100 item list vs hash + lookup would probably be virtually zero.

At the very least void HlslScanContext::deleteKeywordMap() should be removed since it violates the earlier comment.

// A single global usable by all threads, by all versions, by all languages.
// After a single process-level initialization, this is read only and thread safe

@ratchetfreak
Copy link

You can also create a perfect hash and then store it in a 128 sized static array.

@dneto0
Copy link
Contributor

dneto0 commented Mar 15, 2016

A third solution is to use a context object that is explicitly created by the client, and explicitly destroyed by the client. The context object owns all its state, never mixing with the state of another context. This is the preferred solution for APIs in LLVM, and OpenCL. It's very explicit, and hence has no surprises.

@dneto0
Copy link
Contributor

dneto0 commented Mar 15, 2016

HLSL has an #include feature.

My team has been building out an #include feature for GLSL, adding needed bits to the Glslang preprocessor. It's nearly feature complete on the Glslang side with the latest pull request being #198. The client supplies an Includer object to resolve include requests to fully-resolved pathnames and file contents. We're building out the client side in various layers in https://github.com/google/shaderc

We've only done #include "file" support, but no #include <stdfile> support. The hooks are there in the interfaces, but no Glslang preprocessor work has been done for it.

@oscarbg
Copy link

oscarbg commented Mar 25, 2016

Seems Microsoft announed at GDC 2016 that they are migrating from fxc shader compiler to one based on Clang/LLVM supporting HLSL SM5.x and 6.0 and they will open source the effort.. so perhaps better to work from there? coming fall 2016

@johnkslang
Copy link
Member Author

Microsoft announed at GDC 2016 that they are migrating from fxc shader compiler to one based on Clang/LLVM supporting HLSL SM5.x and 6.0 and they will open source the effort

If this includes a parser for HLSL, it might be valuable to this effort, except for being late.

so perhaps better to work from there?

As with GLSL, there may be small source language tweaks desired to communicate correctly with the Vulkan API. Hence, the desire to control our own parser.

@Corillian
Copy link

In that case wouldn't it just be better to fork Microsoft's HLSL parser? Correct me if I'm wrong but there currently doesn't seem to be any sort of reasonable LLVM backend for SPIR-V at the moment. Both LunarGLASS and SPIRV-LLVM have non-trivial shortcomings and a lack of a robust, easy to use toolchain for compiling to optimized SPIR-V seems like a major barrier to Vulkan adoption. With Microsoft apparently investing heavily in a new open source LLVM based HLSL compiler I would think that represents an opportunity to standardize on a common framework. Of course it would be better if somebody could convince them to open source sooner rather than later...

@johnkslang
Copy link
Member Author

In that case wouldn't it just be better to fork Microsoft's HLSL parser?

Yes. Is it available?

With Microsoft apparently investing heavily in a new open source LLVM based HLSL compiler

Will that include the parser, or just post-parsed components?

@Corillian
Copy link

https://www.youtube.com/watch?v=dcDDvoauaz0&feature=youtu.be
The HLSL relevant part starts at ~8m and the QA begins at ~20m. You can also find the slide deck at https://ky0vuq.bl3301.livefilestore.com/y3m7VTWehVTjYVJxlWTYmX_F4cyVmk4dSvJ-4lbzypqkK8yDBkKbI1bw6XAJlLfM2oR-oQIZdzry3Q6vrzS_fuNuFavRbnHDnJkF7giOKgTfanRCV38EJuD_6jEvCB10cUirDCaa_T48ZdeMDKKFoe4qpAnhdG3SBsfaE53gJH_udw/DirectX%2012%20Advancements.pdf?psid=1.

In that video he mentions that they will open source the new LLVM HLSL compiler for everyone within a year or 2, he also says within the 2nd half of this year, which is obviously not a particularly great timeline for anyone interested in adopting Vulkan using HLSL shaders sooner rather than later. That being said it sounds like it's already in active development so theoretically all you'd have to do is plugin a SPIR-V backend and problem solved.

The engine that my company maintains has both D3D11/HLSL and OpenGL/GLSL rendering backends. We prefer working with HLSL and it would be great if we could move to Vulkan with HLSL regardless of whether or not it's using a custom parser or a fork of Microsoft's compiler - whenever that becomes generally available. However the bigger issue for us with Vulkan, regardless of HLSL vs GLSL, is that there is no easy way to go from source to optimized SPIR-V like there is with D3D12 and DXBC.

@johnkslang
Copy link
Member Author

Okay, thanks.

However the bigger issue for us with Vulkan, regardless of HLSL vs GLSL, is that there is no easy way to go from source to optimized SPIR-V like there is with D3D12 and DXBC.

Yes, the SPIR-V ecosystem generally needs SPIR-V modules that can do SPIR-V -> SPIR-V transforms, orthogonally to what the source language was. I suspect a good way of creating such an optimizing module is SPIR-V -> LLVM+metadata -> SPIR-V, rather than a bunch of direct SPIR-V -> SPIR-V transforms reinventing the LLVM transforms rather than reusing them. Different ISVs or tool-chain paths might use different sets of modules/optimizations, based on end usage.

So, I expect SPIR-V -> LLVM+metadata -> SPIR-V tools will exist. It is difficult to standardize LLVM and the metadata, even though it's easy for a specific tool to do its own thing and make it work just fine. Hence, an important aspect of SPIR-V is that it is the point of standardization for everything GPUs and GPU languages need standardized, and is the common meeting ground for all the languages and tools. SPIR-V complements LLVM by being the standard that represents everything GPUs want represented, while LLVM excels at being the tool to do the optimizing transforms.

@dankbaker
Copy link
Contributor

So is the plan here to modify the GLSL compiler to accept HLSL syntax? Is anything functional at the moment or is it just planning stages?

@johnkslang
Copy link
Member Author

So is the plan here to modify the GLSL compiler to accept HLSL syntax?

The plan is to modify glslang to accept the HLSL syntax. The GLSL front end in glslang needs to stay as it is, with the specification grammar, to be the reference front end. However, the new recursive decent front end, aimed at HLSL, can be made to accept a hybrid/superset language, so that SPIR-V features can be properly controlled from the HLL.

Is anything functional at the moment or is it just planning stages?

It's past the planning stages (unless this conversation uncovers something), but only works for trivial shaders. Next step is broadening the functionality.

Recap: Basic plan is to provide, in glslang, a HLSL -> glslang AST -> SPIR-V with a recursive decent parser for two reasons. 1) allow full control over the definition of the HLL, and 2) keep SPIR-V as the standardized rendezvous point for all tools/drivers. If a better code base for the front end becomes available, be flexible about doing the best thing as things change with time.

@dankbaker
Copy link
Contributor

I see. Is there a grammer defined somewhere? How is it being implemented?

HLSL uses (or used to) use yacc/bison for parsing. I think I still remember most of the grammer for it. I'll try to setup a git client and take a look soon myself.

@johnkslang
Copy link
Member Author

johnkslang commented Apr 20, 2016

If we had a real grammar definition that was a correct superset of what we want to do today plus what is coming next, that would be great, and I would use it. Barring that, a guess at a bison grammar risks being painted into a corner. I found, so far, the recursive decent I set up is very nice to work with, without reduce-reduce conflicts to resolve, and theoretically no constraints on looking ahead, and being able to give meaning error messages rather than "syntax error".

I would highly value any input you can freely give on the correct syntax and (especially) semantics of HLSL. Even a short bulleted list of the major differences in GLSL and HLSL semantics, that a normal developer would know, for the same syntax would be useful. But, whatever you can share would be great.

One important note here: because there is no goal to reject invalid HLSL shaders, we can skip all the validation of syntax, so the grammar problem is also greatly simplified due to that.

@dankbaker
Copy link
Contributor

Ok, I'll start by taking a look at what's there. I haven't much experience with recursive decent parsers so it will prob take me some time to wrap my head around it.

GLSL and HLSL are not very different in grammer, honestly. The big difference is HLSL has a more general type definition, (e.g. float1s are essentially the same as floats), more casting promotion/demotions, and the sampler/texture stuff is pretty different.

I think if you have something accepting GLSL code it wouldn't take more then a month or 2 of mods to accept most HLSL code.

@dneto0
Copy link
Contributor

dneto0 commented Apr 21, 2016

Is there a good (complete and precise) spec for HLSL? Microsoft's site has a lot of tutorial-style documentation but it's not quite to level where I'd be confident writing a compiler for it.
I'd be happy to be proven wrong. I haven't worked with HLSL much!

@ratchetfreak
Copy link

@dneto0 one quick google search later: there seems to be a spread out grammar description at https://msdn.microsoft.com/en-us/library/windows/desktop/bb509615%28v=vs.85%29.aspx#

how complete it is I don't know.

@dneto0
Copy link
Contributor

dneto0 commented Apr 21, 2016

@ratchetfreak Agreed. That and some other pages gives grammar level information.
E.g. https://msdn.microsoft.com/en-us/library/windows/desktop/bb509631(v=vs.85).aspx at least says operators have the same precedence as in C.
One of the operators is supposed to be #@ which I can't find a description for. ?!

I'm also concerned about stuff like implicit conversions. What conversions are automatic? Where do they take place? e.g. assignment, arithmetic expressions, in parameter passing.
Are the rules similar to C's "usual arithmetic conversions" that are based on "ranks" for types? (Section 5 paragraph 6 of C++11)
Are there conversions between scalars and vectors? How do they interplay?
There's a lot of detail you need to know if you're compiling something correctly.

Lack of that kind of detail makes me less confident I'd be able to write a correct compiler for HLSL.

A big help would be to see a statement like: "It's just like C except for ....". Then you can build on all the reference material for C or whatever base language.

@dankbaker
Copy link
Contributor

HLSL Grammer is basically c Grammer rules when possible.

I could write out a bnf of the expression parsing if people needed it.
On Apr 21, 2016 11:38 AM, "David Neto" notifications@github.com wrote:

@ratchetfreak https://github.com/ratchetfreak Agreed. That and some
other pages gives grammar level information.
E.g.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb509631(v=vs.85).aspx
at least says operators have the same precedence as in C.
One of the operators is supposed to be #@ which I can't find a description
for. ?!

I'm also concerned about stuff like implicit conversions. What conversions
are automatic? Where do they take place? e.g. assignment, arithmetic
expressions, in parameter passing.
Are the rules similar to C's "usual arithmetic conversions" that are based
on "ranks" for types? (Section 5 paragraph 6 of C++11)
Are there conversions between scalars and vectors? How do they interplay?
There's a lot of detail you need to know if you're compiling something
correctly.

Lack of that kind of detail makes me less confident I'd be able to
write a correct compiler for HLSL.

A big help would be to see a statement like: "It's just like C except for
....". Then you can build on all the reference material for C or whatever
base language.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#200 (comment)

@johnkslang
Copy link
Member Author

My guess of the most difficult area to get right is selection of the right overloaded function under implicit conversion when there is no exact match. But, the front end could issue a request to disambiguate rather than guessing wrong. For normal expressions, knowing the graph of implicit conversions and their priority is enough to get it right. In GLSL it's an unambiguous dag. In C++ it's more complex and cyclic.

@dankbaker
Copy link
Contributor

Yup, that the area that gets tricky. But it's also not a super critical
area because function overload casting isn't a required thing for the
creation of shader code.

There are just lots of little details that can get you such as * is always
a component multiply in HLSL, not a matrix multiply, float1 and floats are
basically the same thing, then there are some rules regarding argument
passing (HLSL is pass by copy), switch statements don't allow fall through,
every statement can have an attribute, etc.

At any rate, I do remember the rules for the finding the best fit
overloaded function due to casting rules if it's really needed.

On Thu, Apr 21, 2016 at 11:51 AM, John Kessenich notifications@github.com
wrote:

My guess of the most difficult area to get right is selection of the right
overloaded function under implicit conversion when there is no exact match.
But, the front end could issue a request to disambiguate rather than
guessing wrong. For normal expressions, knowing the graph of implicit
conversions and their priority is enough to get it right. In GLSL it's an
unambiguous dag. In C++ it's more complex and cyclic.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#200 (comment)

@ghost
Copy link

ghost commented May 19, 2016

The big difference is HLSL has a more general type definition, (e.g. float1s are essentially the same as floats)

I recently did a few ad-hoc experiments around that. It appears to me that floats and float1s are silently implicitly convertible in both directions, but are different underlying types. That is to say, myfunc(float) and myfunc(float1) act like different function signatures, and both overloads can exist simultaneously in the same source without error. (I do not know if that behavior is shader model specific). However, attempting to call one of the functions resulted in an "ambiguous function" error at the call site, presumably due to the implicit conversions. I don't know enough about HLSL to know whether a way to explicitly disambiguate them exists.

Of course, subtleties abound, and it's easy for an experiment to show something different than it seems like it does.

@johnkslang
Copy link
Member Author

Thanks, this will be a great help.

@Alprog
Copy link

Alprog commented Jun 30, 2016

Hello. Can anybody describe current status of hlsl support?
It is look like there are no support of texture or samplers yet. However basic facilities already works and progress is great this month. Do you have rough roadmap? When typical shaders (only simple vert and frag) might be working?

Do you plan support modern hlsl syntax or only legacy DX9-style? Thank you.

@ghost
Copy link

ghost commented Jun 30, 2016

Hi Aiprog,

There is work happening on HLSL support in multiple areas from different people. About textures and samplers in particular: I am working on that area now, but have just started and do not have anything ready yet. I plan to add the DX10 "method" style first with separate declarations of samplers and textures, although most likely this will come with limitations. However I don't know of any reason DX9 style cannot also be added.

@Alprog
Copy link

Alprog commented Jun 30, 2016

Sounds good. Thank you!

@dankbaker
Copy link
Contributor

What are people currently working on? I am ready to drive into Vulkan support this week. Getting close to the point of looking at shader conversion, but I don't want to work in an area where others have made significant progress. I haven't yet downloaded this project and compiled it, is there a link or readme on how to do that?

From looking through what's implemented, I think the #1 thing that will hold us back right now is the method based texture sampling.

Thanks,
-D

@ghost
Copy link

ghost commented Jul 13, 2016

method based texture sampling

I have a pending PR #380 (code review changes happening at the moment) which has the underpinnings for method based texture sampling. It is a narrow vertical path, but once that is in place it should be possible to broaden it fairly easily. I have some of that broadening work on my disk currently.

In a few cases I know of nothing to map a feature to. E.g: immediate sampler state, such as:

uniform sampler2D g_sSamp2d
{
    AddressU = MIRROR;
    AddressV = WRAP;
};

AFAIK, the immediates require API based setup, and there's no defined path for this. The above PR parses the immediate state list, ignores it, and issues a warning in the compilation log. Thoughts about this are welcome...

@johnkslang
Copy link
Member Author

What are people currently working on? I am ready to drive into Vulkan support this week.

See issue #362. It makes some sense to ask or "claiming" one of those with a comment on that issue.

Also, do you have any input about features you want to see that are missing from the list? Overall, the project will get driven from a perspective of what's in real workloads, so contributing from that direction makes sense.

I think @steve-lunarg has a good handle on texturing-related stuff, and I've got the grammar covered, but other things are not yet claimed.

Definitely read the readme before starting.

@johnkslang
Copy link
Member Author

About literal samplers, would be interested in hearing about needs for this, as SPIR-V currently only supports that for OpenCL, not for Vulkan.

@dankbaker
Copy link
Contributor

In terms of literal samplers, some of the 'HLSL' syntax is actually part of the D3D effects systems syntax, which is a library add-on. It's mostly deprecated at this point. Thus, it would be ignored by the main D3D11 runtime, or handled awkwardly (I can't recall how it's handled off hand, but I think it will just show up as reflection data). D3D12 doesn't have this system at all AFAIK.

I have an entire application of shaders to try (maybe ~10,000 lines of shader code), my plan was to try to get some shaders through and see where there are missing areas.

@johnkslang
Copy link
Member Author

@dankbaker, I am interested in hearing about this:

At any rate, I do remember the rules for the finding the best fit overloaded function due to casting rules if it's really needed.

Note that we have an open issue for the GLSL 4.0 variant of this question in issue #142, and one question is whether those rules would also be consistent with HLSL.

@dankbaker
Copy link
Contributor

Btw, is anyone around at siggraph for a f2f?
On Jul 15, 2016 4:21 PM, "John Kessenich" notifications@github.com wrote:

@dankbaker https://github.com/dankbaker, I am interested in hearing
about this:

At any rate, I do remember the rules for the finding the best fit
overloaded function due to casting rules if it's really needed.

Note that we have an open issue for the GLSL 4.0 variant of this question
in issue #142 #142, and
one question is whether those rules would also be consistent with HLSL.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#200 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AC-AU0pZoa8wapSNqtyfdsC7e2hSIy9Sks5qV-vQgaJpZM4HvdmP
.

@Corillian
Copy link

Hey all HLSL Shader Model 6 has been released: https://msdn.microsoft.com/en-us/library/windows/desktop/mt733232(v=vs.85).aspx

@dankbaker
Copy link
Contributor

So I was trying to commit a tiny change just to see if I had write permission, but it didn't work. Is there anything I have to do?

@johnkslang
Copy link
Member Author

@dankbaker You should make your own fork and then submit a Pull Request.

@dankbaker
Copy link
Contributor

Ok, I took a stab at it. Let me know if it works. It's a tiny change just to test out my GIT skills, I have next to no experience with GIT. My whole career has been p4.

@johnkslang
Copy link
Member Author

@dankbaker Looks good so far... it's currently getting run through some bots to make sure it's not breaking something. (Change looks good to me too, on code reading.)

When the bots turn green, I'll merge it in.

@dankbaker
Copy link
Contributor

Is there a standalone app included that generates an output SPIRV similar to fxc or do I have to make my own? All I see is the glslangvalidator

@johnkslang
Copy link
Member Author

glslangValidator -V makes a binary file, add on -H to see human-readable form. Just glslangValidator on its own will print the usage.

@ntakouris
Copy link

Any updates?

@johnkslang
Copy link
Member Author

Lots of activity. See issue #362 and HLSL .

@ntakouris
Copy link

I thought this would continue to be discussed here along with the development process.

Keep up the good work!

@StarsX
Copy link

StarsX commented Aug 18, 2016

Hi, I'm quite interested in the topic that glslang could support HLSL. As I tried to make a simple HLSL shader to replace my GLSL shader, it seems that currently the key issue has not been ready even for a very simple shader. The shader output could not be placed to the correct slot according to the semantics. For example:
GLSL shader:
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (location = 0) out vec2 texcoord;

out gl_PerVertex
{
vec4 gl_Position;
};

void main()
{
texcoord = 2.0 * vec2(gl_VertexIndex >> 1, gl_VertexIndex & 1);

gl_Position = vec4(texcoord * 2.0 - 1.0, 0.5, 1.0);

}

SPV:
Capability Shader
1> 1: ExtInstImport "GLSL.std.450"
1> MemoryModel Logical GLSL450
1> EntryPoint Vertex 4 "main" 9 13 26
1> Source GLSL 400
1> SourceExtension "GL_ARB_separate_shader_objects"
1> SourceExtension "GL_ARB_shading_language_420pack"
1> Name 4 "main"
1> Name 9 "texcoord"
1> Name 13 "gl_VertexIndex"
1> Name 24 "gl_PerVertex"
1> MemberName 24(gl_PerVertex) 0 "gl_Position"
1> Name 26 ""
1> Decorate 9(texcoord) Location 0
1> Decorate 13(gl_VertexIndex) BuiltIn VertexIndex
1> MemberDecorate 24(gl_PerVertex) 0 BuiltIn Position
1> Decorate 24(gl_PerVertex) Block
1> 2: TypeVoid
1> 3: TypeFunction 2
1> 6: TypeFloat 32
1> 7: TypeVector 6(float) 2
1> 8: TypePointer Output 7(fvec2)
1> 9(texcoord): 8(ptr) Variable Output
1> 10: 6(float) Constant 1073741824
1> 11: TypeInt 32 1
1> 12: TypePointer Input 11(int)
1> 13(gl_VertexIndex): 12(ptr) Variable Input
1> 15: 11(int) Constant 1
1> 23: TypeVector 6(float) 4
1> 24(gl_PerVertex): TypeStruct 23(fvec4)
1> 25: TypePointer Output 24(gl_PerVertex)
1> 26: 25(ptr) Variable Output
1> 27: 11(int) Constant 0
1> 30: 6(float) Constant 1065353216
1> 33: 6(float) Constant 1056964608
1> 37: TypePointer Output 23(fvec4)
1> 4(main): 2 Function None 3
1> 5: Label
1> 14: 11(int) Load 13(gl_VertexIndex)
1> 16: 11(int) ShiftRightArithmetic 14 15
1> 17: 6(float) ConvertSToF 16
1> 18: 11(int) Load 13(gl_VertexIndex)
1> 19: 11(int) BitwiseAnd 18 15
1> 20: 6(float) ConvertSToF 19
1> 21: 7(fvec2) CompositeConstruct 17 20
1> 22: 7(fvec2) VectorTimesScalar 21 10
1> Store 9(texcoord) 22
1> 28: 7(fvec2) Load 9(texcoord)
1> 29: 7(fvec2) VectorTimesScalar 28 10
1> 31: 7(fvec2) CompositeConstruct 30 30
1> 32: 7(fvec2) FSub 29 31
1> 34: 6(float) CompositeExtract 32 0
1> 35: 6(float) CompositeExtract 32 1
1> 36: 23(fvec4) CompositeConstruct 34 35 33 30
1> 38: 37(ptr) AccessChain 26 27
1> Store 38 36
1> Return
1> FunctionEnd

and my corresponding HLSL shader:
void main(uint vid : SV_VertexID,
out float4 Pos : SV_Position,
out float2 Tex : location0)
{
Tex = 2.0 * float2(vid >> 1, vid & 1);
Pos = float4(Tex * 2.0 - 1.0, 0.5, 1.0);
}

Firstly, I had found that currently glslang could not parse the semantic correctly, so I simply modified the source code to satisfy my requirement:
void HlslParseContext::handleSemantic(TType& type, const TString& semantic)
{
// TODO: need to know if it's an input or an output
// The following sketches what needs to be done, but can't be right
// without taking into account stage and input/output.

if (semantic == "PSIZE")
    type.getQualifier().builtIn = EbvPointSize;
else if (semantic == "SV_Position")
{
    if (language == EShLangFragment)
        type.getQualifier().builtIn = EbvFragCoord;
    else
    {
        type.getQualifier().builtIn = EbvPosition;
        type.getQualifier().storage = EvqVaryingOut;
        //type.getQualifier().storage = EvqOut;
    }
}
else if (semantic == "POSITION")
    type.getQualifier().builtIn = EbvPosition;
else if (semantic == "FOG")
    type.getQualifier().builtIn = EbvFogFragCoord;
else if (semantic == "DEPTH" || semantic == "SV_Depth")
    type.getQualifier().builtIn = EbvFragDepth;
else if (semantic == "VFACE" || semantic == "SV_IsFrontFace")
    type.getQualifier().builtIn = EbvFace;
//else if (semantic == "VPOS" || semantic == "SV_Position")
else if (semantic == "VPOS")
    type.getQualifier().builtIn = EbvFragCoord;
else if (semantic == "SV_ClipDistance")
    type.getQualifier().builtIn = EbvClipDistance;
else if (semantic == "SV_CullDistance")
    type.getQualifier().builtIn = EbvCullDistance;
else if (semantic == "SV_VertexID")
    type.getQualifier().builtIn = EbvVertexId;
else if (semantic == "SV_ViewportArrayIndex")
    type.getQualifier().builtIn = EbvViewportIndex;
else
{
    unsigned int location;
    int suc = sscanf(semantic.c_str(), "location%u", &location);
    if (suc) {
        type.getQualifier().layoutLocation = location;
        type.getQualifier().storage = EvqVaryingOut;
        //type.getQualifier().storage = EvqOut;
    }
}

}

Thus, the SPV of the HLSL shader becomes:
1> Capability Shader
1> 1: ExtInstImport "GLSL.std.450"
1> MemoryModel Logical GLSL450
1> EntryPoint Vertex 4 "main" 9 13 27
1> Name 4 "main"
1> Name 9 "Tex"
1> Name 13 "vid"
1> Name 27 "Pos"
1> Decorate 9(Tex) Location 0
1> Decorate 13(vid) BuiltIn VertexId
1> Decorate 27(Pos) BuiltIn Position
1> 2: TypeVoid
1> 3: TypeFunction 2
1> 6: TypeFloat 32
1> 7: TypeVector 6(float) 2
1> 8: TypePointer Input 7(fvec2)
1> 9(Tex): 8(ptr) Variable Input
1> 10: 6(float) Constant 1073741824
1> 11: TypeInt 32 0
1> 12: TypePointer Input 11(int)
1> 13(vid): 12(ptr) Variable Input
1> 15: TypeInt 32 1
1> 16: 15(int) Constant 1
1> 20: 11(int) Constant 1
1> 25: TypeVector 6(float) 4
1> 26: TypePointer Input 25(fvec4)
1> 27(Pos): 26(ptr) Variable Input
1> 30: 6(float) Constant 1065353216
1> 33: 6(float) Constant 1056964608
1> 4(main): 2 Function None 3
1> 5: Label
1> 14: 11(int) Load 13(vid)
1> 17: 11(int) ShiftRightLogical 14 16
1> 18: 6(float) ConvertUToF 17
1> 19: 11(int) Load 13(vid)
1> 21: 11(int) BitwiseAnd 19 20
1> 22: 6(float) ConvertUToF 21
1> 23: 7(fvec2) CompositeConstruct 18 22
1> 24: 7(fvec2) VectorTimesScalar 23 10
1> Store 9(Tex) 24
1> 28: 7(fvec2) Load 9(Tex)
1> 29: 7(fvec2) VectorTimesScalar 28 10
1> 31: 7(fvec2) CompositeConstruct 30 30
1> 32: 7(fvec2) FSub 29 31
1> 34: 6(float) CompositeExtract 32 0
1> 35: 6(float) CompositeExtract 32 1
1> 36: 25(fvec4) CompositeConstruct 34 35 33 30
1> Store 27(Pos) 36
1> Return
1> FunctionEnd

It is almost as same as the GLSL version, except that
8: TypePointer Input 7(fvec2)
9(Tex): 8(ptr) Variable Input
26: TypePointer Input 25(fvec4)
27(Pos): 26(ptr) Variable Input

Even I used "out", the SPV instructions are still input.
If this issue can be handled soon, I think glslang for HLSL will be useful for simple shaders practically.

@johnkslang
Copy link
Member Author

Tex and Pos are now outputs (issue tracked elsewhere).

Closing this, as issues can now be handled as specific individual issues.

Thanks for all the input!

@jiyongjeong
Copy link

@johnkslang
I am trying to use glslang to translate hlsl into spir-v. Can I actually build glslang to compile hlsl into spir-v? How can I do it?

@johnkslang
Copy link
Member Author

Yes, this should work. If you can build glslangValidator, HLSL support is included automatically, accessed via the -D option. There are many other options, see the usage statement. There are some pending features, but lots of HLSL shaders now work.

@jiyongjeong
Copy link

jiyongjeong commented Oct 24, 2016

@johnkslang
Thanks for you replying. I used glslangValidator to translate hlsl into spir-v successfully. However, I don’t know how many hlsl functionalities could be translated into spir-v by now. Could I know which part is working and which is not?

@johnkslang
Copy link
Member Author

See issue #362.

qingyuanzNV pushed a commit to qingyuanzNV/glslang that referenced this issue Oct 18, 2022
…ce-odr-spv-khr-expect-assume

Support SPV_KHR_linkonce_odr and SPV_KHR_expect_assume
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests