<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jul 14, 2017 at 2:57 AM, Iago Toral <span dir="ltr"><<a href="mailto:itoral@igalia.com" target="_blank">itoral@igalia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Thu, 2017-07-13 at 12:41 -0700, Jason Ekstrand wrote:<br>
> ---<br>
> src/compiler/spirv/nir_spirv.<wbr>h | 1 +<br>
> src/compiler/spirv/spirv_to_<wbr>nir.c | 42<br>
> ++++++++++++++++++++++++++++++<wbr>++---<br>
> src/compiler/spirv/vtn_cfg.c <wbr> | 5 +++--<br>
> src/compiler/spirv/vtn_<wbr>private.h | 23 +++++++++++++++++--<br>
> src/compiler/spirv/vtn_<wbr>variables.c | 45<br>
> ++++++++++++++++++++++++++++++<wbr>+++++---<br>
> 5 files changed, 106 insertions(+), 10 deletions(-)<br>
><br>
> diff --git a/src/compiler/spirv/nir_<wbr>spirv.h<br>
> b/src/compiler/spirv/nir_<wbr>spirv.h<br>
> index 7f16866..83577fb 100644<br>
> --- a/src/compiler/spirv/nir_<wbr>spirv.h<br>
> +++ b/src/compiler/spirv/nir_<wbr>spirv.h<br>
> @@ -51,6 +51,7 @@ struct nir_spirv_supported_extensions {<br>
> bool image_write_without_format;<br>
> bool int64;<br>
> bool multiview;<br>
> + bool variable_pointers;<br>
> };<br>
> <br>
> nir_function *spirv_to_nir(const uint32_t *words, size_t word_count,<br>
> diff --git a/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> index 6e35f83..e60c9f7 100644<br>
> --- a/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> +++ b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> @@ -185,6 +185,13 @@ vtn_ssa_value(struct vtn_builder *b, uint32_t<br>
> value_id)<br>
> case vtn_value_type_ssa:<br>
> return val->ssa;<br>
> <br>
> + case vtn_value_type_pointer:<br>
> + assert(val->pointer-><wbr>ptr_type && val->pointer->ptr_type-<br>
> >type);<br>
> + struct vtn_ssa_value *ssa =<br>
> + vtn_create_ssa_<wbr>value(b, val->pointer->ptr_type->type);<br>
> + ssa->def = vtn_pointer_to_ssa(b, val->pointer);<br>
> + return ssa;<br>
> +<br>
> default:<br>
> unreachable("Invalid type for an SSA value");<br>
> }<br>
> @@ -861,9 +868,20 @@ vtn_handle_type(struct vtn_builder *b, SpvOp<br>
> opcode,<br>
> vtn_value(b, w[3], vtn_value_type_type)->type;<br>
> <br>
> val->type->base_type = vtn_base_type_pointer;<br>
> - val->type->type = NULL;<br>
<br>
</div></div>Right, we use rzalloc for val->type so this was redundant.<br>
<span class=""><br>
> val->type->storage_<wbr>class = storage_class;<br>
> val->type->deref = deref_type;<br>
> +<br>
> + struct vtn_type *without_array = deref_type;<br>
> + while (without_array->base_type == vtn_base_type_array)<br>
> + without_array = without_array->array_element;<br>
><br>
<br>
</span>What's the purpose of this loop? 'without_array' isn't used for<br>
anything here...<span class=""><br></span></blockquote><div><br></div><div>None, aparently. I had it in there for some reason in an older version but that reason has aparently been lost. I'll drop it.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> + if (storage_class == SpvStorageClassUniform ||<br>
> + storage_class == SpvStorageClassStorageBuffer) {<br>
> + /* These can actually be stored to nir_variables and used<br>
> as SSA<br>
> + * values so they need a real glsl_type.<br>
> + */<br>
> + val->type->type = glsl_vector_type(GLSL_TYPE_<wbr>UINT, 2);<br>
> + }<br>
> break;<br>
> }<br>
<br>
</span>(...)<br>
<span class=""><br>
> static inline struct vtn_value *<br>
> vtn_push_value(struct vtn_builder *b, uint32_t value_id,<br>
> enum vtn_value_type value_type)<br>
> @@ -517,8 +530,14 @@ static inline struct vtn_value *<br>
> vtn_push_ssa(struct vtn_builder *b, uint32_t value_id,<br>
> struct vtn_type *type, struct vtn_ssa_value *ssa)<br>
> {<br>
> - struct vtn_value *val = vtn_push_value(b, value_id,<br>
> vtn_value_type_ssa);<br>
> - val->ssa = ssa;<br>
> + struct vtn_value *val;<br>
> + if (type->base_type == vtn_base_type_pointer) {<br>
> + val = vtn_push_value(b, value_id, vtn_value_type_pointer);<br>
> + val->pointer = vtn_pointer_from_ssa(b, ssa->def, type);<br>
> + } else {<br>
> + val = vtn_push_value(b, value_id, vtn_value_type_ssa);<br>
> + val->ssa = ssa;<br>
> + }<br>
<br>
</span>So you start using the 'type' parameter here... I guess it is okay if<br>
it was added in the previous patch then.<br>
<div><div class="h5"><br>
> return val;<br>
> }<br>
> <br>
> diff --git a/src/compiler/spirv/vtn_<wbr>variables.c<br>
> b/src/compiler/spirv/vtn_<wbr>variables.c<br>
> index a9e2dbf..47f111b 100644<br>
> --- a/src/compiler/spirv/vtn_<wbr>variables.c<br>
> +++ b/src/compiler/spirv/vtn_<wbr>variables.c<br>
> @@ -223,8 +223,7 @@ vtn_pointer_dereference(struct vtn_builder *b,<br>
> <wbr>struct vtn_pointer *base,<br>
> <wbr>struct vtn_access_chain *deref_chain)<br>
> {<br>
> - if (base->mode == vtn_variable_mode_ubo ||<br>
> - base->mode == vtn_variable_mode_ssbo) {<br>
> + if (vtn_pointer_uses_ssa_offset(<wbr>base)) {<br>
> return vtn_ssa_offset_pointer_<wbr>dereference(b, base,<br>
> deref_chain);<br>
> } else {<br>
> return vtn_access_chain_pointer_<wbr>dereference(b, base,<br>
> deref_chain);<br>
> @@ -1478,6 +1477,47 @@ vtn_storage_class_to_mode(<wbr>SpvStorageClass<br>
> class,<br>
> return mode;<br>
> }<br>
> <br>
> +nir_ssa_def *<br>
> +vtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr)<br>
> +{<br>
> + if (ptr->offset && ptr->block_index) {<br>
> + return nir_vec2(&b->nb, ptr->block_index, ptr->offset);<br>
> + } else {<br>
> + /* If we don't have an offset or block index, then we must be<br>
> a pointer<br>
> + * to the variable itself.<br>
> + */<br>
> + assert(!ptr->offset && !ptr->block_index);<br>
> +<br>
> + /* We can't handle a pointer to an array of descriptors<br>
> because we have<br>
> + * no way of knowing later on that we need to add to update<br>
> the block<br>
> + * index when dereferencing.<br>
> + */<br>
> + assert(ptr->var && ptr->var->type->base_type ==<br>
> vtn_base_type_struct);<br>
> +<br>
> + return nir_vec2(&b->nb, vtn_variable_resource_index(b, ptr-<br>
> >var, NULL),<br>
> + <wbr> nir_imm_int(&b->nb, 0));<br>
> + }<br>
> +}<br>
> +<br>
> +struct vtn_pointer *<br>
> +vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,<br>
> + struct vtn_type *ptr_type)<br>
> +{<br>
> + assert(ssa->num_components == 2 && ssa->bit_size == 32);<br>
> + assert(ptr_type->base_type == vtn_base_type_pointer);<br>
> + assert(ptr_type->deref-><wbr>base_type != vtn_base_type_pointer);<br>
> +<br>
> + struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer);<br>
> + ptr->mode = vtn_storage_class_to_mode(ptr_<wbr>type->storage_class,<br>
> + <wbr> ptr_type, NULL);<br>
> + ptr->type = ptr_type->deref;<br>
> + ptr->ptr_type = ptr_type;<br>
> + ptr->block_index = nir_channel(&b->nb, ssa, 0);<br>
> + ptr->offset = nir_channel(&b->nb, ssa, 1);<br>
><br>
<br>
</div></div>So here we always create (block,offset) pointers, which I guess means<br>
that we can't call this with ssa values that represent pointers to<br>
variables</blockquote><div><br></div><div>Correct. Variable pointers only applies to SSBOs. (Our implementation also works for UBOs but I don't think the spec requires that.)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> (the else branch in vtn_pointer_to_ssa)... is that checked<br>
anywhere? It doesn't look like vtn_push_ssa() check anything, so I<br>
wonder if there is a chance that this can happen.<br><div class="HOEnZb"><div class="h5"></div></div></blockquote><div><br></div><div>Hrm... Maybe not? I'm happy to add some type checks.<br><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
> + return ptr;<br>
> +}<br>
> +<br>
> static bool<br>
> is_per_vertex_inout(const struct vtn_variable *var, gl_shader_stage<br>
> stage)<br>
> {<br>
> @@ -1503,7 +1543,6 @@ vtn_create_variable(struct vtn_builder *b,<br>
> struct vtn_value *val,<br>
> {<br>
> assert(ptr_type->base_type == vtn_base_type_pointer);<br>
> struct vtn_type *type = ptr_type->deref;<br>
> - assert(type->base_type != vtn_base_type_pointer);<br>
> <br>
> struct vtn_type *without_array = type;<br>
> while(glsl_type_is_array(<wbr>without_array->type))<br>
</div></div></blockquote></div><br></div></div>