[Mesa-dev] [PATCH 5/5] spirv: Make images, samplers, and sampled images normal SSA values
Jason Ekstrand
jason at jlekstrand.net
Sat Sep 22 21:39:22 UTC 2018
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
More information about the mesa-dev
mailing list