Instead of treating image, sampler, and combined image sampler SSA values as pointers and special-casing them various places, we now allow them to be part of regular SSA values. Among other things, this means that composites of opaque types should now work correctly. --- src/compiler/spirv/spirv_to_nir.c | 53 ++++++++++------------ src/compiler/spirv/vtn_cfg.c | 70 +++++++++++++++--------------- src/compiler/spirv/vtn_private.h | 7 ++- src/compiler/spirv/vtn_variables.c | 51 ++++++++++------------ 4 files changed, 86 insertions(+), 95 deletions(-)
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 2ad83196e46..b6e9d9fe11a 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -1860,25 +1860,19 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, const uint32_t *w, unsigned count) { if (opcode == SpvOpSampledImage) { - 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->type = - vtn_value(b, w[1], vtn_value_type_type)->type; - 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; + struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type; + struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, res_type->type); + ssa->sampled_image = ralloc(b, struct vtn_sampled_image); + ssa->sampled_image->type = res_type; + ssa->sampled_image->image = vtn_ssa_value(b, w[3])->image; + ssa->sampled_image->sampler = vtn_ssa_value(b, w[4])->sampler; + vtn_push_ssa(b, w[2], res_type, ssa); return; } else if (opcode == SpvOpImage) { - struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); - struct vtn_value *src_val = vtn_untyped_value(b, w[3]); - if (src_val->value_type == vtn_value_type_sampled_image) { - val->pointer = src_val->sampled_image->image; - } else { - vtn_assert(src_val->value_type == vtn_value_type_pointer); - val->pointer = src_val->pointer; - } + struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type; + struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, res_type->type); + ssa->image = vtn_ssa_value(b, w[3])->sampled_image->image; + vtn_push_ssa(b, w[2], res_type, ssa); return; } @@ -1886,14 +1880,14 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa); struct vtn_sampled_image sampled; - struct vtn_value *sampled_val = vtn_untyped_value(b, w[3]); - if (sampled_val->value_type == vtn_value_type_sampled_image) { - sampled = *sampled_val->sampled_image; + struct vtn_value *sampled_val = vtn_value(b, w[3], vtn_value_type_ssa); + if (sampled_val->type->base_type == vtn_base_type_sampled_image) { + sampled = *sampled_val->ssa->sampled_image; } else { - vtn_assert(sampled_val->value_type == vtn_value_type_pointer); - sampled.type = sampled_val->pointer->type; + vtn_assert(sampled_val->type->base_type == vtn_base_type_image); + sampled.type = sampled_val->type; sampled.image = NULL; - sampled.sampler = sampled_val->pointer; + sampled.sampler = sampled_val->ssa->image; } const struct glsl_type *image_type = sampled.type->type; @@ -2319,13 +2313,13 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, break; case SpvOpImageQuerySize: - image.image = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; + image.image = vtn_ssa_value(b, w[3])->image; image.coord = NULL; image.sample = NULL; break; case SpvOpImageRead: - image.image = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; + image.image = vtn_ssa_value(b, w[3])->image; image.coord = get_image_coord(b, w[4]); if (count > 5 && (w[5] & SpvImageOperandsSampleMask)) { @@ -2337,7 +2331,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, break; case SpvOpImageWrite: - image.image = vtn_value(b, w[1], vtn_value_type_pointer)->pointer; + image.image = vtn_ssa_value(b, w[1])->image; image.coord = get_image_coord(b, w[2]); /* texel = w[3] */ @@ -3836,12 +3830,11 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, break; case SpvOpImageQuerySize: { - struct vtn_pointer *image = - vtn_value(b, w[3], vtn_value_type_pointer)->pointer; - if (glsl_type_is_image(image->type->type)) { + struct vtn_value *val = vtn_value(b, w[3], vtn_value_type_ssa); + if (glsl_type_is_image(val->type->type)) { vtn_handle_image(b, opcode, w, count); } else { - vtn_assert(glsl_type_is_sampler(image->type->type)); + vtn_assert(glsl_type_is_sampler(val->type->type)); vtn_handle_texture(b, opcode, w, count); } break; diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c index 1020b2722f4..747f6d40694 100644 --- a/src/compiler/spirv/vtn_cfg.c +++ b/src/compiler/spirv/vtn_cfg.c @@ -138,6 +138,19 @@ vtn_ssa_value_add_to_call_params(struct vtn_builder *b, } break; + case vtn_base_type_sampled_image: + call->params[(*param_idx)++] = + nir_src_for_ssa(vtn_pointer_to_ssa(b, value->sampled_image->image)); + call->params[(*param_idx)++] = + nir_src_for_ssa(vtn_pointer_to_ssa(b, value->sampled_image->sampler)); + break; + + case vtn_base_type_image: + case vtn_base_type_sampler: + call->params[(*param_idx)++] = + nir_src_for_ssa(vtn_pointer_to_ssa(b, value->image)); + break; + default: call->params[(*param_idx)++] = nir_src_for_ssa(value->def); break; @@ -165,6 +178,26 @@ vtn_ssa_value_load_function_param(struct vtn_builder *b, } break; + case vtn_base_type_sampled_image: { + value->sampled_image = ralloc(b, struct vtn_sampled_image); + value->sampled_image->type = type; + + struct vtn_type *sampler_type = rzalloc(b, struct vtn_type); + sampler_type->base_type = vtn_base_type_sampler; + sampler_type->type = glsl_bare_sampler_type(); + + value->sampled_image->image = + vtn_load_param_pointer(b, type, (*param_idx)++); + value->sampled_image->sampler = + vtn_load_param_pointer(b, sampler_type, (*param_idx)++); + break; + } + + case vtn_base_type_image: + case vtn_base_type_sampler: + value->image = vtn_load_param_pointer(b, type, (*param_idx)++); + break; + default: value->def = nir_load_param(&b->nb, b->func_param_idx++); break; @@ -199,17 +232,7 @@ vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode, struct vtn_type *arg_type = vtn_callee->type->params[i]; unsigned arg_id = w[4 + i]; - if (arg_type->base_type == vtn_base_type_sampled_image) { - struct vtn_sampled_image *sampled_image = - vtn_value(b, arg_id, vtn_value_type_sampled_image)->sampled_image; - - call->params[param_idx++] = - nir_src_for_ssa(&sampled_image->image->deref->dest.ssa); - call->params[param_idx++] = - nir_src_for_ssa(&sampled_image->sampler->deref->dest.ssa); - } else if (arg_type->base_type == vtn_base_type_pointer || - arg_type->base_type == vtn_base_type_image || - arg_type->base_type == vtn_base_type_sampler) { + if (arg_type->base_type == vtn_base_type_pointer) { struct vtn_pointer *pointer = vtn_value(b, arg_id, vtn_value_type_pointer)->pointer; call->params[param_idx++] = @@ -300,34 +323,13 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode, vtn_assert(b->func_param_idx < b->func->impl->function->num_params); - if (type->base_type == vtn_base_type_sampled_image) { - /* Sampled images are actually two parameters. The first is the - * image and the second is the sampler. - */ - 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->type = type; - - struct vtn_type *sampler_type = rzalloc(b, struct vtn_type); - sampler_type->base_type = vtn_base_type_sampler; - sampler_type->type = glsl_bare_sampler_type(); - - val->sampled_image->image = - vtn_load_param_pointer(b, type, b->func_param_idx++); - val->sampled_image->sampler = - vtn_load_param_pointer(b, sampler_type, b->func_param_idx++); - } else if (type->base_type == vtn_base_type_pointer && - type->type != NULL) { + if (type->base_type == vtn_base_type_pointer && type->type != NULL) { /* This is a pointer with an actual storage type */ struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); nir_ssa_def *ssa_ptr = nir_load_param(&b->nb, b->func_param_idx++); val->pointer = vtn_pointer_from_ssa(b, ssa_ptr, type); - } else if (type->base_type == vtn_base_type_pointer || - type->base_type == vtn_base_type_image || - type->base_type == vtn_base_type_sampler) { + } else if (type->base_type == vtn_base_type_pointer) { struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); val->pointer = diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index a31202d1295..46575469744 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -112,7 +112,6 @@ enum vtn_value_type { vtn_value_type_ssa, vtn_value_type_extension, vtn_value_type_image_pointer, - vtn_value_type_sampled_image, }; enum vtn_branch_type { @@ -250,9 +249,14 @@ const uint32_t * vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start, const uint32_t *end, vtn_instruction_handler handler); +struct vtn_pointer; + struct vtn_ssa_value { union { nir_ssa_def *def; + struct vtn_sampled_image *sampled_image; + struct vtn_pointer *image; + struct vtn_pointer *sampler; struct vtn_ssa_value **elems; }; @@ -513,7 +517,6 @@ struct vtn_value { nir_constant *constant; struct vtn_pointer *pointer; struct vtn_image_pointer *image; - struct vtn_sampled_image *sampled_image; struct vtn_function *func; struct vtn_block *block; struct vtn_ssa_value *ssa; diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index 358ff4bef7a..9ec35fa8380 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -868,6 +868,22 @@ _vtn_variable_load_store(struct vtn_builder *b, bool load, } return; + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: + vtn_fail_if(!load, "Attempted to store to an image or sampler"); + (*inout) = vtn_create_ssa_value(b, ptr->type->type); + if (ptr->type->base_type == vtn_base_type_sampled_image) { + (*inout)->sampled_image = ralloc(b, struct vtn_sampled_image); + (*inout)->sampled_image->type = ptr->type; + (*inout)->sampled_image->image = ptr; + (*inout)->sampled_image->sampler = ptr; + } else { + assert(ptr->type->base_type == vtn_base_type_image || + ptr->type->base_type == vtn_base_type_sampler); + (*inout)->image = ptr; + } + return; + case GLSL_TYPE_ARRAY: case GLSL_TYPE_STRUCT: { unsigned elems = glsl_get_length(ptr->type->type); @@ -1895,29 +1911,12 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, } struct vtn_type *ptr_type = vtn_value(b, w[1], vtn_value_type_type)->type; - struct vtn_value *base_val = vtn_untyped_value(b, w[3]); - if (base_val->value_type == vtn_value_type_sampled_image) { - /* This is rather insane. SPIR-V allows you to use OpSampledImage - * to combine an array of images with a single sampler to get an - * array of sampled images that all share the same sampler. - * Fortunately, this means that we can more-or-less ignore the - * sampler when crawling the access chain, but it does leave us - * with this rather awkward little special-case. - */ - 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->type = base_val->sampled_image->type; - val->sampled_image->image = - vtn_pointer_dereference(b, base_val->sampled_image->image, chain); - val->sampled_image->sampler = base_val->sampled_image->sampler; - } else { - vtn_assert(base_val->value_type == vtn_value_type_pointer); - struct vtn_value *val = - vtn_push_value(b, w[2], vtn_value_type_pointer); - val->pointer = vtn_pointer_dereference(b, base_val->pointer, chain); - val->pointer->ptr_type = ptr_type; - } + struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); + struct vtn_pointer *base = + vtn_value(b, w[3], vtn_value_type_pointer)->pointer; + + val->pointer = vtn_pointer_dereference(b, base, chain); + val->pointer->ptr_type = ptr_type; break; } @@ -1939,12 +1938,6 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, vtn_assert_types_equal(b, opcode, res_type, src_val->type->deref); - if (glsl_type_is_image(res_type->type) || - glsl_type_is_sampler(res_type->type)) { - vtn_push_value(b, w[2], vtn_value_type_pointer)->pointer = src; - return; - } - vtn_push_ssa(b, w[2], res_type, vtn_variable_load(b, src)); break; } -- 2.17.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev