Invalid entry point for shader when using HLSL->SPIR-V->OpenGL.

huangapple go评论58阅读模式
英文:

Invalid entry point for shader when using HLSL->SPIR-V->OpenGL

问题

I am trying to implement a system so that I can use HLSL in my OpenGL application, since it can be compiled to SPIR-V, and SPIR-V can be translated to something that works with e.g DirectX.

However, I receive an error when specializing the shader:

glSpecializeShaderARB("vert" is not a valid entry point for shader)

I am using shaderc.net, and compiling to SPIR-V via that, then following standard procedure, I've attached the SPIR-V source code to a shader object.

ShaderHandle shaderHandle = GL.CreateShader(source.GLShaderType);
GL.ShaderBinary(Utility.Wrap(shaderHandle), ShaderBinaryFormat.ShaderBinaryFormatSpirV, result.CodePointer, (int)result.CodeLength);
GL.SpecializeShader(shaderHandle, source.EntryPoint, 0, Array.Empty<uint>(), Array.Empty<uint>());

The result variable, is just the compilation result from shaderc, and Utility.Wrap is what I use to simply convert a single variable to a ReadOnlySpan.

I'll append that I am using OpenTK for the OpenGL bindings.

I've tried a variety of shader sources. This one actually decompiles into what seems like valid GLSL in RenderDoc:

struct VERTEX_DATA
{
    float3 pos;
};

float4 vert(VERTEX_DATA vertex) : SV_POSITION
{
    return float4(vertex.pos, 0);
}

Here's the output from the RenderDoc decompiler

#version 450

layout(location = 0) in vec3 vertex_pos;

void main()
{
    gl_Position = vec4(vertex_pos, 0.0);
}

which seems like valid GLSL, but it results in the error I've specified.

EDIT:
There was a request for dissasembly. Here's RenderDoc SPIR-V disasm

; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 11
; Bound: 47
; Schema: 0
OpCapability Shader
%2 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %vert "vert" %vertex_pos %_entryPointOutput
%1 = OpString "test.hlsl"
OpSource HLSL 500 %1 "// OpModuleProcessed entry-point vert
// OpModuleProcessed client opengl100
// OpModuleProcessed target-env opengl
// OpModuleProcessed hlsl-offsets
#line 1
struct VERTEX_DATA
{
    float3 pos;
};

float4 vert(VERTEX_DATA vertex) : SV_POSITION
{
    return float4(vertex.pos, 0);
}
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
OpSourceExtension "GL_GOOGLE_include_directive"
OpName %vert "vert"
OpName %vertex_pos "vertex.pos"
OpName %_entryPointOutput "@entryPointOutput"
OpDecorate %vertex_pos Location 0
OpDecorate %_entryPointOutput BuiltIn Position
%void = OpTypeVoid
%4 = OpTypeFunction %void
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%v4float = OpTypeVector %float 4
%float_0 = OpConstant %float 0
%_ptr_Input_v3float = OpTypePointer Input %v3float
%vertex_pos = OpVariable %_ptr_Input_v3float Input
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
OpLine %1 7 1
%vert = OpFunction %void None %4
OpNoLine
%6 = OpLabel
OpLine %1 7 0
%31 = OpLoad %v3float %vertex_pos
OpLine %1 8 0
%43 = OpCompositeExtract %float %31 0
%44 = OpCompositeExtract %float %31 1
%45 = OpCompositeExtract %float %31 2
%46 = OpCompositeConstruct %v4float %43 %44 %45 %float_0
OpLine %1 7 0
OpStore %_entryPointOutput %46
OpReturn
OpFunctionEnd
英文:

I am trying to implement a system so that I can use HLSL in my OpenGL application, since it can be compiled to SPIR-V, and SPIR-V can be translated to something that works with e.g DirectX.

However, I receive an error when specializing the shader:

glSpecializeShaderARB(&quot;vert&quot; is not a valid entry point for shader)

I am using shaderc.net, and compiling to SPIR-V via that, then following standard procedure, I've attached the SPIR-V source code to a shader object.

ShaderHandle shaderHandle = GL.CreateShader(source.GLShaderType);
GL.ShaderBinary(Utility.Wrap(shaderHandle), ShaderBinaryFormat.ShaderBinaryFormatSpirV, result.CodePointer, (int)result.CodeLength);
GL.SpecializeShader(shaderHandle, source.EntryPoint, 0, Array.Empty&lt;uint&gt;(), Array.Empty&lt;uint&gt;());

The result variable, is just the compilation result from shaderc, and Utility.Wrap is what I use to simply convert a single variable to a ReadOnlySpan.

I'll append that I am using OpenTK for the OpenGL bindings.

I've tried a variety of shader sources. This one actually decompiles into what seems like valid GLSL in RenderDoc:

struct VERTEX_DATA
{
    float3 pos;
};

float4 vert(VERTEX_DATA vertex) : SV_POSITION
{
    return float4(vertex.pos, 0);
}

Here's the output from the RenderDoc decompiler

#version 450

layout(location = 0) in vec3 vertex_pos;

void main()
{
    gl_Position = vec4(vertex_pos, 0.0);
}

which seems like valid GLSL, but it results in the error I've specified.

EDIT:
There was a request for dissasembly. Here's RenderDoc SPIR-V disasm

; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 11
; Bound: 47
; Schema: 0
               OpCapability Shader
          %2 = OpExtInstImport &quot;GLSL.std.450&quot;
               OpMemoryModel Logical GLSL450
               OpEntryPoint Vertex %vert &quot;vert&quot; %vertex_pos %_entryPointOutput
          %1 = OpString &quot;test.hlsl&quot;
               OpSource HLSL 500 %1 &quot;// OpModuleProcessed entry-point vert
// OpModuleProcessed client opengl100
// OpModuleProcessed target-env opengl
// OpModuleProcessed hlsl-offsets
#line 1
struct VERTEX_DATA
{
    float3 pos;
};

float4 vert(VERTEX_DATA vertex) : SV_POSITION
{
    return float4(vertex.pos, 0);
}&quot;
               OpSourceExtension &quot;GL_GOOGLE_cpp_style_line_directive&quot;
               OpSourceExtension &quot;GL_GOOGLE_include_directive&quot;
               OpName %vert &quot;vert&quot;
               OpName %vertex_pos &quot;vertex.pos&quot;
               OpName %_entryPointOutput &quot;@entryPointOutput&quot;
               OpDecorate %vertex_pos Location 0
               OpDecorate %_entryPointOutput BuiltIn Position
       %void = OpTypeVoid
          %4 = OpTypeFunction %void
      %float = OpTypeFloat 32
    %v3float = OpTypeVector %float 3
    %v4float = OpTypeVector %float 4
    %float_0 = OpConstant %float 0
%_ptr_Input_v3float = OpTypePointer Input %v3float
 %vertex_pos = OpVariable %_ptr_Input_v3float Input
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
               OpLine %1 7 1
       %vert = OpFunction %void None %4
               OpNoLine
          %6 = OpLabel
               OpLine %1 7 0
         %31 = OpLoad %v3float %vertex_pos
               OpLine %1 8 0
         %43 = OpCompositeExtract %float %31 0
         %44 = OpCompositeExtract %float %31 1
         %45 = OpCompositeExtract %float %31 2
         %46 = OpCompositeConstruct %v4float %43 %44 %45 %float_0
               OpLine %1 7 0
               OpStore %_entryPointOutput %46
               OpReturn
               OpFunctionEnd

答案1

得分: 0

我成功解决了问题,只需不再使用shaderc.net。出于某种原因(我不知道是什么原因),它似乎无法正常工作。然而,一旦我切换到Vortice.ShaderCompiler,基本上只是一种替代方案,一些不同的命名约定,然后就可以了,它突然完美地工作了。

所以,我猜答案是:
不要使用shaderc.net,它已经3年没有维护了,使用一些更现代的替代方案,有一些不错的选择。

英文:

I managed to resolve the issue by simply not using shaderc.net. For whatever reason(which I do not know) it doesn't seem to work properly. However, as soon as I switched to Vortice.ShaderCompiler which pretty much just was a slot-in alternative, some different naming conventions and that's it, it suddenly worked perfectly.

So, I guess the answer is:
Don't use shaderc.net, it is broken and hasn't been maintained in 3 years, use something up-to-date instead, there are some nice alternatives.

huangapple
  • 本文由 发表于 2023年4月6日 23:42:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75951372.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定