KhronosGroup/SPIRV-Cross

hlsl -> spirv -> glsl compilation lost texture binding points

Hochheilige opened this issue · 2 comments

Hello!
I decided to write shaders in hlsl to use it with my OpenGl render. My fragment shader has following textures and sampler

Texture2D<float4> diffuse_map : register(t0, space0);
Texture2D<float4> specular_map : register(t1, space0);
SamplerState samplerState : register(s0, space0);

Using dxc I compile this shader to spirv and want to generate OpenGL readable glsl code using spirv_cross. But for some reason finall glsl code lost the binding points and a space (but this is not so important for ogl). So after generating glsl I have something like this:

uniform Sampler2D _113;
uniform Sampler2D _115;

I use dxc and spirv_cross from my c++ code to compile shaders at runtime and have an ability to recompile it. For dxc I pass only -spirv argument, for spirv_cross I do something like this:

    spirv_cross::CompilerGLSL glsl_compiler(spirv);
    spirv_cross::CompilerGLSL::Options options;
    options.version = 450;
    options.es = false;   
    glsl_compiler.set_common_options(options);
    glsl_compiler.build_combined_image_samplers();
    std::string glsl_code = glsl_compiler.compile();

And as far as I understand build_combined_image_samplers generates this two uniforms from my textures and sampler, but why there is no bindings points at final output and is it possible to generate bindings?

why there is no bindings points at final output?

Normally, that happens because OpenGL below 4.2 requires the GL_ARB_explicit_uniform_location and GL_ARB_shading_language_420pack extensions for that. But, you're setting version to 450 explicitly, and enable_420pack_extension is true by default, so that can't be it.

In this case, I'd say it's because those uniforms are generated by SPIRV-Cross, but SPIRV-Cross didn't copy the DecorationBinding from the original uniforms. And how could it? The original image and sampler uniforms each have a different binding; which one should it copy? What about in the case where multiple images are used with multiple samplers? What if the image and sampler are from different descriptor sets (Vulkan)/register spaces (D3D12/HLSL)?

is it possible to generate bindings?

Yes, but it's somewhat involved. It entails finding the generated uniforms after build_combined_image_samplers() has been called, and explicitly setting DecorationBinding on them. The Compiler::get_shader_resources() and Compiler::set_decoration() methods will facilitate this. This should happen, of course, before compile() is called.

I see. Thank you.
Your solution works for me. I used set_decoration and successfully add bindings to my samplers.