From 9b6a8d17424ac5fa11ccf44c02da2a237088cb76 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 26 May 2020 13:54:34 +0200 Subject: [PATCH] spirv: fix using OpSampledImage with OpUndef instead of OpType{Image,Sampler} This seems valid per the SPIR-V spec to use OpSampledImage with OpUndef instead of OpTypeImage or OpTypeSampler. When the image operand is undefined, SPIRV->NIR emits an undef instruction that can be removed later by the compiler. This fixes shader compilation crashes with Red Dead Redemption II. Cc: mesa-stable@lists.freedesktop.org> Signed-off-by: Samuel Pitoiset Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index cfe180c0489..10c5de55216 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -2259,10 +2259,23 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_sampled_image); val->sampled_image = ralloc(b, struct vtn_sampled_image); - val->sampled_image->image = - vtn_value(b, w[3], vtn_value_type_pointer)->pointer; - val->sampled_image->sampler = - vtn_value(b, w[4], vtn_value_type_pointer)->pointer; + + /* It seems valid to use OpSampledImage with OpUndef instead of + * OpTypeImage or OpTypeSampler. + */ + if (vtn_untyped_value(b, w[3])->value_type == vtn_value_type_undef) { + val->sampled_image->image = NULL; + } else { + val->sampled_image->image = + vtn_value(b, w[3], vtn_value_type_pointer)->pointer; + } + + if (vtn_untyped_value(b, w[4])->value_type == vtn_value_type_undef) { + val->sampled_image->sampler = NULL; + } else { + val->sampled_image->sampler = + vtn_value(b, w[4], vtn_value_type_pointer)->pointer; + } return; } else if (opcode == SpvOpImage) { struct vtn_value *src_val = vtn_untyped_value(b, w[3]); @@ -2287,6 +2300,11 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, image = sampled_val->pointer; } + if (!image) { + vtn_push_value(b, w[2], vtn_value_type_undef); + return; + } + nir_deref_instr *image_deref = vtn_pointer_to_deref(b, image); nir_deref_instr *sampler_deref = sampler ? vtn_pointer_to_deref(b, sampler) : NULL; -- 2.30.2