Skip to content

Commit 7979193

Browse files
Archiver GL: enabled support of GL_ANGLE_multi_draw extension
1 parent 31a72fd commit 7979193

File tree

1 file changed

+112
-2
lines changed

1 file changed

+112
-2
lines changed

Graphics/Archiver/src/Archiver_GL.cpp

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,85 @@ struct SerializedResourceSignatureImpl::SignatureTraits<PipelineResourceSignatur
5959
namespace
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+
62141
struct 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

Comments
 (0)