diff --git a/reference/opt/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag b/reference/opt/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag new file mode 100644 index 00000000..4734c89c --- /dev/null +++ b/reference/opt/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag @@ -0,0 +1,8 @@ +#version 320 es +precision mediump float; +precision highp int; + +void main() +{ +} + diff --git a/reference/opt/shaders/asm/frag/out-of-bounds-access.asm.frag b/reference/opt/shaders/asm/frag/out-of-bounds-access.asm.frag new file mode 100644 index 00000000..4734c89c --- /dev/null +++ b/reference/opt/shaders/asm/frag/out-of-bounds-access.asm.frag @@ -0,0 +1,8 @@ +#version 320 es +precision mediump float; +precision highp int; + +void main() +{ +} + diff --git a/reference/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag b/reference/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag new file mode 100644 index 00000000..eddb3829 --- /dev/null +++ b/reference/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag @@ -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; + } +} + diff --git a/reference/shaders/asm/frag/out-of-bounds-access.asm.frag b/reference/shaders/asm/frag/out-of-bounds-access.asm.frag new file mode 100644 index 00000000..080283d4 --- /dev/null +++ b/reference/shaders/asm/frag/out-of-bounds-access.asm.frag @@ -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; + } +} + diff --git a/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag b/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag new file mode 100644 index 00000000..628a9f5b --- /dev/null +++ b/shaders/asm/frag/out-of-bounds-access-opspecconstant.asm.frag @@ -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 diff --git a/shaders/asm/frag/out-of-bounds-access.asm.frag b/shaders/asm/frag/out-of-bounds-access.asm.frag new file mode 100644 index 00000000..542b74b2 --- /dev/null +++ b/shaders/asm/frag/out-of-bounds-access.asm.frag @@ -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 diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index cdc1c6b6..f06ed2c0 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -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) { - expr += "."; - expr += index_to_swizzle(index); + bool out_of_bounds = (index >= type->vecsize); + + if (!is_packed && !row_major_matrix_needs_conversion) + { + expr += "."; + 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(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 += "[";