@@ -59,6 +59,85 @@ struct SerializedResourceSignatureImpl::SignatureTraits<PipelineResourceSignatur
5959namespace
6060{
6161
62+ #if !DILIGENT_NO_GLSLANG
63+ static bool GetUseGLAngleMultiDrawWorkaround (const ShaderCreateInfo& ShaderCI)
64+ {
65+ if (ShaderCI.SourceLanguage == SHADER_SOURCE_LANGUAGE_GLSL_VERBATIM ||
66+ ShaderCI.Desc .ShaderType != SHADER_TYPE_VERTEX)
67+ return false ;
68+
69+ const auto Extensions = GetGLSLExtensions (ShaderCI.GLSLExtensions );
70+ for (const auto & Ext : Extensions)
71+ {
72+ if (Ext.first == " GL_ANGLE_multi_draw" )
73+ {
74+ return Ext.second == " enable" || Ext.second == " require" ;
75+ }
76+ }
77+
78+ return false ;
79+ }
80+
81+ static void PatchSourceForWebGL (std::string& Source, SHADER_TYPE ShaderType)
82+ {
83+ // Remove location qualifiers
84+ {
85+ // WebGL only supports location qualifiers for VS inputs and FS outputs.
86+ const std::string InOutQualifier = ShaderType == SHADER_TYPE_VERTEX ? " out " : " in " ;
87+
88+ auto layout_pos = Source.find (" layout" );
89+ while (layout_pos != std::string::npos)
90+ {
91+ // layout(location = 3) flat out int _VSOut_PrimitiveID;
92+ // ^
93+ // layout_pos
94+
95+ const auto declaration_end_pos = Source.find_first_of (" ;{" , layout_pos + 6 );
96+ if (declaration_end_pos == std::string::npos)
97+ break ;
98+ // layout(location = 3) flat out int _VSOut_PrimitiveID;
99+ // ^
100+ // declaration_end_pos
101+
102+ // layout(std140) uniform cbPrimitiveAttribs {
103+ // ^
104+ // declaration_end_pos
105+
106+ const std::string Declaration = Source.substr (layout_pos, declaration_end_pos - layout_pos);
107+ // layout(location = 3) flat out int _VSOut_PrimitiveID
108+
109+ if (Declaration.find (InOutQualifier) != std::string::npos)
110+ {
111+ const auto closing_paren_pos = Source.find (' )' , layout_pos);
112+ if (closing_paren_pos == std::string::npos)
113+ break ;
114+
115+ // layout(location = 3) flat out int _VSOut_PrimitiveID;
116+ // ^
117+ // closing_paren_pos
118+
119+ for (size_t i = layout_pos; i <= closing_paren_pos; ++i)
120+ Source[i] = ' ' ;
121+ // flat out int _VSOut_PrimitiveID;
122+ }
123+
124+ layout_pos = Source.find (" layout" , layout_pos + 6 );
125+ }
126+ }
127+
128+ if (ShaderType == SHADER_TYPE_VERTEX)
129+ {
130+ // Replace gl_DrawIDARB with gl_DrawID
131+ size_t pos = Source.find (" gl_DrawIDARB" );
132+ while (pos != std::string::npos)
133+ {
134+ Source.replace (pos, 12 , " gl_DrawID" );
135+ pos = Source.find (" gl_DrawIDARB" , pos + 9 );
136+ }
137+ }
138+ }
139+ #endif
140+
62141struct CompiledShaderGL final : SerializedShaderImpl::CompiledShader
63142{
64143 String UnrolledSource;
@@ -150,13 +229,28 @@ struct CompiledShaderGL final : SerializedShaderImpl::CompiledShader
150229 std::string OptimizedGLSL;
151230
152231#if !DILIGENT_NO_GLSLANG
232+
233+ RENDER_DEVICE_TYPE CompileDeviceType = DeviceType;
234+ RenderDeviceShaderVersionInfo MaxShaderVersion = GLShaderCI.DeviceInfo .MaxShaderVersion ;
235+
236+ const bool UseGLAngleMultiDrawWorkaround = GetUseGLAngleMultiDrawWorkaround (ShaderCI);
237+ if (UseGLAngleMultiDrawWorkaround)
238+ {
239+ // Since GLSLang does not support GL_ANGLE_multi_draw extension, we need to compile the shader
240+ // for desktop GL.
241+ CompileDeviceType = RENDER_DEVICE_TYPE_GL;
242+
243+ // Use GLSL4.6 as it uses the gl_DrawID built-in variable, same as the ANGLE extension.
244+ MaxShaderVersion.GLSL = {4 , 6 };
245+ }
246+
153247 const std::string GLSLSourceString = BuildGLSLSourceString (
154248 {
155249 ShaderCI,
156250 GLShaderCI.AdapterInfo ,
157251 GLShaderCI.DeviceInfo .Features ,
158- GLShaderCI. DeviceInfo . Type ,
159- GLShaderCI. DeviceInfo . MaxShaderVersion ,
252+ CompileDeviceType ,
253+ MaxShaderVersion,
160254 TargetGLSLCompiler::glslang,
161255 GLProps.ZeroToOneClipZ , // Note that this is not the same as GLShaderCI.DeviceInfo.NDC.MinZ == 0
162256 });
@@ -192,6 +286,17 @@ struct CompiledShaderGL final : SerializedShaderImpl::CompiledShader
192286 Options.es = IsES;
193287 Options.version = GLSLVersion.Major * 100 + GLSLVersion.Minor * 10 ;
194288
289+ if (UseGLAngleMultiDrawWorkaround)
290+ {
291+ // gl_DrawID is not supported in GLES, so compile the shader for desktop GL.
292+ // This is OK as we strip the version directive and extensions and only leave the GLSL code.
293+ Options.es = false ;
294+
295+ // Use GLSL4.1 as WebGL does not support binding qualifiers.
296+ Options.version = 410 ;
297+ Options.enable_420pack_extension = false ;
298+ }
299+
195300 Options.separate_shader_objects = GLShaderCI.DeviceInfo .Features .SeparablePrograms ;
196301 // On some targets (WebGPU), uninitialized variables are banned.
197302 Options.force_zero_initialized_variables = true ;
@@ -223,6 +328,11 @@ struct CompiledShaderGL final : SerializedShaderImpl::CompiledShader
223328 // #endif
224329 Parsing::StripPreprocessorDirectives (OptimizedGLSL, {{" version" }, {" extension" }, {" error" }});
225330
331+ if (UseGLAngleMultiDrawWorkaround)
332+ {
333+ PatchSourceForWebGL (OptimizedGLSL, ShaderCI.Desc .ShaderType );
334+ }
335+
226336 AppendShaderSourceLanguageDefinition (OptimizedGLSL, (SourceLang != SHADER_SOURCE_LANGUAGE_DEFAULT) ? SourceLang : ShaderCI.SourceLanguage );
227337#endif
228338
0 commit comments