Clamp vector element access to vector size.

In cases where we know the size of the vector and the index at compile
time, we can check if it's accessing in bounds and rely in undefined
behavior otherwise.

Signed-off-by: Sebastián Aedo <saedo@codeweavers.com>
This commit is contained in:
Sebastián Aedo 2021-11-11 12:57:57 -03:00
parent e9cc640334
commit 905b8244e7
7 changed files with 151 additions and 10 deletions

View File

@ -0,0 +1,8 @@
#version 320 es
precision mediump float;
precision highp int;
void main()
{
}

View File

@ -0,0 +1,8 @@
#version 320 es
precision mediump float;
precision highp int;
void main()
{
}

View File

@ -0,0 +1,15 @@
#version 320 es
precision mediump float;
precision highp int;
const uint _15 = 3u;
void main()
{
vec3 v = vec3(0.0);
if (false)
{
v[0] = 99.0;
}
}

View File

@ -0,0 +1,14 @@
#version 320 es
precision mediump float;
precision highp int;
void main()
{
vec3 v = vec3(0.0);
if (false)
{
v.x = 99.0;
v.x = 88.0;
}
}

View File

@ -0,0 +1,42 @@
; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 10
; Bound: 21
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
OpSource ESSL 320
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
OpSourceExtension "GL_GOOGLE_include_directive"
OpName %main "main"
OpName %v "v"
OpDecorate %v RelaxedPrecision
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%_ptr_Function_v3float = OpTypePointer Function %v3float
%float_0 = OpConstant %float 0
%11 = OpConstantComposite %v3float %float_0 %float_0 %float_0
%bool = OpTypeBool
%false = OpConstantFalse %bool
%float_99 = OpConstant %float 99
%uint = OpTypeInt 32 0
%uint_spec_3 = OpSpecConstant %uint 3
%_ptr_Function_float = OpTypePointer Function %float
%main = OpFunction %void None %3
%5 = OpLabel
%v = OpVariable %_ptr_Function_v3float Function
OpStore %v %11
OpSelectionMerge %15 None
OpBranchConditional %false %14 %15
%14 = OpLabel
%20 = OpAccessChain %_ptr_Function_float %v %uint_spec_3
OpStore %20 %float_99
OpBranch %15
%15 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,47 @@
; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 10
; Bound: 21
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
OpSource ESSL 320
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
OpSourceExtension "GL_GOOGLE_include_directive"
OpName %main "main"
OpName %v "v"
OpDecorate %v RelaxedPrecision
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%_ptr_Function_v3float = OpTypePointer Function %v3float
%float_0 = OpConstant %float 0
%11 = OpConstantComposite %v3float %float_0 %float_0 %float_0
%bool = OpTypeBool
%false = OpConstantFalse %bool
%float_99 = OpConstant %float 99
%float_88 = OpConstant %float 88
%uint = OpTypeInt 32 0
%uint_3 = OpConstant %uint 3
%sint = OpTypeInt 32 1
%sint_3 = OpConstant %sint -1
%_ptr_Function_float = OpTypePointer Function %float
%main = OpFunction %void None %3
%5 = OpLabel
%v = OpVariable %_ptr_Function_v3float Function
OpStore %v %11
OpSelectionMerge %15 None
OpBranchConditional %false %14 %15
%14 = OpLabel
%20 = OpAccessChain %_ptr_Function_float %v %uint_3
OpStore %20 %float_99
%99 = OpAccessChain %_ptr_Function_float %v %sint_3
OpStore %99 %float_88
OpBranch %15
%15 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -8894,30 +8894,37 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
is_packed);
}
if (is_literal && !is_packed && !row_major_matrix_needs_conversion)
if (is_literal)
{
bool out_of_bounds = (index >= type->vecsize);
if (!is_packed && !row_major_matrix_needs_conversion)
{
expr += ".";
expr += index_to_swizzle(index);
expr += index_to_swizzle(out_of_bounds ? 0 : index);
}
else
{
// For packed vectors, we can only access them as an array, not by swizzle.
expr += join("[", out_of_bounds ? 0 : index, "]");
}
}
else if (ir.ids[index].get_type() == TypeConstant && !is_packed && !row_major_matrix_needs_conversion)
{
auto &c = get<SPIRConstant>(index);
bool out_of_bounds = (c.scalar() >= type->vecsize);
if (c.specialization)
{
// If the index is a spec constant, we cannot turn extract into a swizzle.
expr += join("[", to_expression(index), "]");
expr += join("[", out_of_bounds ? "0" : to_expression(index), "]");
}
else
{
expr += ".";
expr += index_to_swizzle(c.scalar());
expr += index_to_swizzle(out_of_bounds ? 0 : c.scalar());
}
}
else if (is_literal)
{
// For packed vectors, we can only access them as an array, not by swizzle.
expr += join("[", index, "]");
}
else
{
expr += "[";