HLSL: crash, while compiling HULL shader
Try opened this issue · comments
Found, while working on spirv-cross tessellation shader. This shader is result of cross-compilation of simple glsl shader.
Shader code:
static float4 gl_Position;
static float gl_TessLevelOuter[4];
static float gl_TessLevelInner[2];
static float3 vFoo;
struct SPIRV_Cross_HS_Point_Input
{
float4 gl_Position : SV_Position;
};
struct SPIRV_Cross_Input
{
};
struct SPIRV_Cross_Output
{
float3 vFoo : TEXCOORD0;
float gl_TessLevelOuter[3] : SV_TessFactor;
float gl_TessLevelInner : SV_InsideTessFactor;
};
struct SPIRV_Cross_HS_Point_Output
{
};
void tesc_main(InputPatch<SPIRV_Cross_HS_Point_Input,32> gl_in)
{
gl_TessLevelInner[0] = 8.8999996185302734375f;
gl_TessLevelInner[1] = 6.900000095367431640625f;
gl_TessLevelOuter[0] = 8.8999996185302734375f;
gl_TessLevelOuter[1] = 6.900000095367431640625f;
gl_TessLevelOuter[2] = 3.900000095367431640625f;
gl_TessLevelOuter[3] = 4.900000095367431640625f;
vFoo = 1.0f.xxx;
}
SPIRV_Cross_Output tesc_patch_constant(InputPatch<SPIRV_Cross_HS_Point_Input, 32> gl_in)
{
tesc_main(gl_in);
SPIRV_Cross_Output stage_output;
stage_output.gl_TessLevelOuter[0] = gl_TessLevelOuter[0];
stage_output.gl_TessLevelOuter[1] = gl_TessLevelOuter[1];
stage_output.gl_TessLevelOuter[2] = gl_TessLevelOuter[2];
stage_output.gl_TessLevelInner = gl_TessLevelInner[0];
stage_output.vFoo = vFoo;
return stage_output;
}
[outputcontrolpoints(1)]
[domain("tri")]
[partitioning("fractional_even")]
[outputtopology("triangle_cw")]
[patchconstantfunc("tesc_patch_constant")]
SPIRV_Cross_HS_Point_Output main(SPIRV_Cross_Input stage_input, InputPatch<SPIRV_Cross_HS_Point_Input, 32> gl_in)
{
tesc_main(gl_in);
SPIRV_Cross_HS_Point_Output stage_output;
return stage_output;
}
GLSL:
#version 310 es
#extension GL_EXT_tessellation_shader : require
layout(location = 0) patch out vec3 vFoo;
layout(vertices = 1) out;
void main()
{
gl_TessLevelInner[0] = 8.9;
gl_TessLevelInner[1] = 6.9;
gl_TessLevelOuter[0] = 8.9;
gl_TessLevelOuter[1] = 6.9;
gl_TessLevelOuter[2] = 3.9;
gl_TessLevelOuter[3] = 4.9;
vFoo = vec3(1.0);
}
While, tessellation shader without output is not particulary useful kind of shader, but it's valid one (from syntax point of view).
Crash stack:
1 std::vector<glslang::TTypeLoc,glslang::pool_allocator<glslang::TTypeLoc>>::operator[] vector 1484
2 glslang::TType::TType Types.h 1643
3 glslang::HlslParseContext::flatten hlslParseHelper.cpp 1190
4 <lambda_c0d8cf1ab0cf9dc4c0965069d8b0a181>::operator() hlslParseHelper.cpp 2099
5 glslang::HlslParseContext::transformEntryPoint hlslParseHelper.cpp 2106
6 glslang::HlslParseContext::handleFunctionDefinition hlslParseHelper.cpp 1680
7 glslang::HlslGrammar::acceptFunctionBody hlslGrammar.cpp 2691
8 glslang::HlslGrammar::acceptFunctionDefinition hlslGrammar.cpp 2683
9 glslang::HlslGrammar::acceptDeclaration hlslGrammar.cpp 432
10 glslang::HlslGrammar::acceptDeclarationList hlslGrammar.cpp 164
11 glslang::HlslGrammar::acceptCompilationUnit hlslGrammar.cpp 129
12 glslang::HlslGrammar::parse hlslGrammar.cpp 66
13 glslang::HlslParseContext::parseShaderStrings hlslParseHelper.cpp 134
14 `anonymous namespace'::DoFullParse::operator() ShaderLang.cpp 1236
15 `anonymous namespace'::ProcessDeferred<`anonymous namespace'::DoFullParse> ShaderLang.cpp 1019
16 `anonymous namespace'::CompileDeferred ShaderLang.cpp 1325
17 glslang::TShader::parse ShaderLang.cpp 1915
18 glslang::TShader::parse ShaderLang.h 670
19 CompileAndLinkShaderUnits StandAlone.cpp 1331
20 CompileAndLinkShaderFiles StandAlone.cpp 1487
Context:
// Top level variable flattening: construct data
void HlslParseContext::flatten(const TVariable& variable, bool linkage, bool arrayed)
{
const TType& type = variable.getType();
// If it's a standalone built-in, there is nothing to flatten
if (type.isBuiltIn() && !type.isStruct())
return;
auto entry = flattenMap.insert(std::make_pair(variable.getUniqueId(),
TFlattenData(type.getQualifier().layoutBinding,
type.getQualifier().layoutLocation)));
// if flattening arrayed io struct, array each member of dereferenced type
if (arrayed) {
const TType dereferencedType(type, 0); // <--- fetching of first member of structure, without checking for struct size
flatten(variable, dereferencedType, entry.first->second, variable.getName(), linkage,
type.getQualifier(), type.getArraySizes());
} else {
flatten(variable, type, entry.first->second, variable.getName(), linkage,
type.getQualifier(), nullptr);
}
}