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

[HLSL] Support SPIR-V from HLSL for OpenGL #1417

Open
Xottab-DUTY opened this issue Jun 25, 2018 · 16 comments
Open

[HLSL] Support SPIR-V from HLSL for OpenGL #1417

Xottab-DUTY opened this issue Jun 25, 2018 · 16 comments

Comments

@Xottab-DUTY
Copy link
Contributor

Sadly, but you can't currently use glslang to compile HLSL shaders for OpenGL right now.

Waiting forward for the moment when this will be finally available..

@godlikepanos
Copy link
Contributor

godlikepanos commented Jun 25, 2018

The moment has arrived!

The first way is to use glslang to compile to HLSL to SPIR-V and then use SPIRV-Cross to convert SPIR-V to GLSL.

The second way -that might work- is to use SPIR-V directly if your driver supports the GL_ARB_gl_spirv extension.

You can experiment with all the compilers and cross compilers here: http://shader-playground.timjones.io/d1af9d9a29f86e412b1b23e68a7e3998

@Xottab-DUTY
Copy link
Contributor Author

Xottab-DUTY commented Jun 26, 2018

Are you sure that SPIR-V compiled for Vulkan would work for OpenGL?
The same question goes for GLSL output from SPIR-V Cross. Will it work with OpenGL?

P.S. anyway, the moment has not arrived. You can't directly compile HLSL to OpenGL SPIR-V. I've tried to do this and got this:
ERROR: HLSL currently only supported when requesting SPIR-V for Vulkan.

@johnkslang
Copy link
Member

johnkslang commented Jun 26, 2018

OpenGL is a different execution environment that supports different features than the Vulkan execution environment.

It is probably not too difficult to plumb HLSL -> glslang -> SPIR-V-for-OpenGL, if we have good understanding of ecosystem need for it.

@Xottab-DUTY
Copy link
Contributor Author

Can't wait to see it working. =)

@Xottab-DUTY
Copy link
Contributor Author

@johnkslang, any progress on this? At least a little bit?

@ryao
Copy link

ryao commented Oct 21, 2018

Silly question, but why don’t you just use mojoshader to convert from HLSL to GLSL?

https://hg.icculus.org/icculus/mojoshader/file/tip/mojoshader.h

That is supposed to work for Shader Model 1.0 through 3.0. For 4.0 and 5.0, you can probably reuse the DXVK shader compiler code:

https://github.com/doitsujin/dxvk/tree/master/src/dxbc

It converts directly from DXBC to SPIR-V.

@Xottab-DUTY
Copy link
Contributor Author

@ryao, thank you! I didn't heard about these, I'll try.

@MarnixKuijs
Copy link

When I use glslangValidator version 7.11.3113 and I try to compile Hlsl into opengl spirv it compiles without any warning or error. With line: glslangValidator -e main -G -D "file.frag" -o "file.spv"
But the moment I try to use the compiled shaders I get a read access violation in nvogl.dll. If I compile it to vulkan spirv, cross compile it back to glsl than compile again to opengl spirv I don't get this read acces violation (So for now this is the method I will be using).
I was wondering if the read access violation is a problem on my end or if compiling hlsl into opengl spirv isn't fully supported yet and I just have to wait longer?

@Xottab-DUTY
Copy link
Contributor Author

Is this still an issue or it was implemented?

@paroj
Copy link
Contributor

paroj commented Jan 3, 2020

seems like it crashes only if texture sampling is used. A simple hello-world fragment HLSL shader displaying uv coordinates did work.

@fromasmtodisasm
Copy link

fromasmtodisasm commented Dec 31, 2020

seems like it crashes only if texture sampling is used. A simple hello-world fragment HLSL shader displaying uv coordinates did work.

I fully support it, I have the same problem, the semantics of samplers for opengle is not respected, if you look at the spirv-cross reflect, we will see that the code with the samplers is compiled into this

 "separate_images" : [
        {
            "type" : "texture2D",
            "name" : "screenTexture",
            "set" : 0,
            "binding" : 0
        }
    ],
    "separate_samplers" : [
        {
            "type" : "sampler",
            "name" : "linearSampler",
            "set" : 0,
            "binding" : 0
        }
    ]

which, as far as I understand, makes the video card break when trying to execute such code

but the exit from glsl to spirv should contain only this

    "textures" : [
        {
            "type" : "sampler2D",
            "name" : "tex",
            "location" : 0,
            "set" : 0,
            "binding" : 0
        }
    ]

Why don't you generate semantically correct code for opengl from hlsl?

after all, this is quite possible, for example, if there are 2 identical textures and one sampler for them, then in the code it will be just 2 samplers, this is already a problem with the opengle application in order to bind the same sampler to 2 different texture slots, although this is not problem.

On the other hand, if there are 2 textures and two different samplers, then this is also not a problem, it would be just 2 different sampler2d uniforms in the glsl code, here, too, the opengl application itself will bind 2 different samplers to 2 different texture slots.

why can't you implement similar behavior in code generator?

it would be absolutely stupid to force users to make such a large chain of calls
glslangvalidator (hlsl) -> spirv-cross (spirv) -> glslangvalidator (glsl) -> semantic correct spirv

PS: probably this instructions break execution of shader

         %80 = OpLoad %20 %screenTexture
         %81 = OpLoad %24 %linearSampler
         %82 = OpSampledImage %28 %80 %81

code that do sampling generated from glsl

%main = OpFunction %void None %3
          %5 = OpLabel
         %14 = OpLoad %11 %tex
         %18 = OpLoad %v2float %tc
         %19 = OpImageSampleImplicitLod %v4float %14 %18
               OpStore %fragColor %19
               OpReturn
               OpFunctionEnd

from hlsl with separate texture and sampler

 %main = OpFunction %void None %3
          %5 = OpLabel
         %51 = OpLoad %v2float %stage_input_IN_tc
               OpStore %IN_tc %51
         %80 = OpLoad %20 %screenTexture
         %81 = OpLoad %24 %linearSampler
         %82 = OpSampledImage %28 %80 %81
         %83 = OpLoad %v2float %IN_tc
         %84 = OpImageSampleImplicitLod %v4float %82 %83
               OpStore %_entryPointOutput %84
         %76 = OpLoad %v4float %_entryPointOutput
               OpStore %_entryPointOutput__entryPointOutput %76
               OpReturn
               OpFunctionEnd

maybe it is possible to set up the pipeline in the opengl so that this shader works correctly? then no problem, but it seems to me this execution model is specific for the vulkan environment

@greg-lunarg
Copy link
Contributor

I will take a look...

@greg-lunarg
Copy link
Contributor

It appears to me that -G was not intended to work with -D, that is, with HLSL source. As such I will create an issue to fix the documentation and give an error message for this to avoid future confusion.

I think the status of this issue stands: it is a request for an enhancement. As such, and since there is a workaround with spirv-cross, I likely will not be able to find time to implement this in the foreseeable future.

If someone wishes to implement it, I would highly recommend posting an implementation plan here first and gets my approval. Specifically, it is not clear I would approve a design that pulls spirv-cross into this project.

@Metalhead33
Copy link

So, if I understand it correctly, the only way to use HLSL shaders in an OpenGL game is to first convert them to SPIRV with Glslang and then to GLSL with SPIRV-Cross? Directly using the SPIRV doesn't work, even in GL 4.6?

@untodesu
Copy link

So, if I understand it correctly, the only way to use HLSL shaders in an OpenGL game is to first convert them to SPIRV with Glslang and then to GLSL with SPIRV-Cross? Directly using the SPIRV doesn't work, even in GL 4.6?

It should be possible if you're willing to chain-compile HLSL -> SPIR-V for Vulkan -> GLSL -> SPIR-V for OpenGL 4.6

@arcady-lunarg
Copy link
Contributor

Unfortunately, yes, the currently supported option is to use that cross-compilation pipeline. The issue is that OpenGL SPIR-V supports slightly different features compared to Vulkan SPIR-V. You can see the differences listed in the spec here: https://registry.khronos.org/OpenGL/extensions/ARB/ARB_gl_spirv.txt

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