KhronosGroup / glslang

Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator.
Other
2.95k stars 819 forks source link

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

Open Xottab-DUTY opened 6 years ago

Xottab-DUTY commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

Can't wait to see it working. =)

Xottab-DUTY commented 5 years ago

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

ryao commented 5 years ago

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 commented 5 years ago

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

MarnixKuijs commented 5 years ago

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 commented 5 years ago

Is this still an issue or it was implemented?

paroj commented 4 years ago

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

fromasmtodisasm commented 3 years ago

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 commented 3 years ago

I will take a look...

greg-lunarg commented 3 years ago

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 commented 2 months ago

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 commented 2 months ago

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 commented 2 months ago

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