[Mesa-dev] [PATCH 1/2] spirv/nir: add support for ImageGatherExtended
Ilia Mirkin
imirkin at alum.mit.edu
Thu Dec 15 02:23:54 UTC 2016
ping
On Sun, Nov 27, 2016 at 4:22 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> The strategy is to do the same thing that the GLSL lower_offset_arrays
> pass does - create 4 separate texture gather ops, one per offset, and
> read in the results from each gather's w component to recreate the
> desired result.
>
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
> src/compiler/spirv/spirv_to_nir.c | 76 +++++++++++++++++++++++++++++++++++----
> 1 file changed, 69 insertions(+), 7 deletions(-)
>
> diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
> index 34968a4..73d0643 100644
> --- a/src/compiler/spirv/spirv_to_nir.c
> +++ b/src/compiler/spirv/spirv_to_nir.c
> @@ -1487,6 +1487,7 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
> (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod);
>
> /* Now we need to handle some number of optional arguments */
> + const struct vtn_ssa_value *gather_offsets = NULL;
> if (idx < count) {
> uint32_t operands = w[idx++];
>
> @@ -1513,8 +1514,10 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
> operands & SpvImageOperandsConstOffsetMask)
> (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_offset);
>
> - if (operands & SpvImageOperandsConstOffsetsMask)
> - assert(!"Constant offsets to texture gather not yet implemented");
> + if (operands & SpvImageOperandsConstOffsetsMask) {
> + gather_offsets = vtn_ssa_value(b, w[idx++]);
> + (*p++) = (nir_tex_src){};
> + }
>
> if (operands & SpvImageOperandsSampleMask) {
> assert(texop == nir_texop_txf_ms);
> @@ -1548,13 +1551,16 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
> }
>
> nir_deref_var *sampler = vtn_access_chain_to_deref(b, sampled.sampler);
> + nir_deref *texture;
> if (sampled.image) {
> nir_deref_var *image = vtn_access_chain_to_deref(b, sampled.image);
> - instr->texture = nir_deref_as_var(nir_copy_deref(instr, &image->deref));
> + texture = &image->deref;
> } else {
> - instr->texture = nir_deref_as_var(nir_copy_deref(instr, &sampler->deref));
> + texture = &sampler->deref;
> }
>
> + instr->texture = nir_deref_as_var(nir_copy_deref(instr, texture));
> +
> switch (instr->op) {
> case nir_texop_tex:
> case nir_texop_txb:
> @@ -1584,10 +1590,66 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
> assert(glsl_get_vector_elements(ret_type->type) ==
> nir_tex_instr_dest_size(instr));
>
> + nir_ssa_def *def;
> + nir_instr *instruction;
> + if (gather_offsets) {
> + assert(glsl_get_base_type(gather_offsets->type) == GLSL_TYPE_ARRAY);
> + assert(glsl_get_length(gather_offsets->type) == 4);
> + nir_tex_instr *instrs[4] = {instr, NULL, NULL, NULL};
> +
> + /* Copy the current instruction 4x */
> + for (uint32_t i = 1; i < 4; i++) {
> + instrs[i] = nir_tex_instr_create(b->shader, instr->num_srcs);
> + instrs[i]->op = instr->op;
> + instrs[i]->coord_components = instr->coord_components;
> + instrs[i]->sampler_dim = instr->sampler_dim;
> + instrs[i]->is_array = instr->is_array;
> + instrs[i]->is_shadow = instr->is_shadow;
> + instrs[i]->is_new_style_shadow = instr->is_new_style_shadow;
> + instrs[i]->component = instr->component;
> + instrs[i]->dest_type = instr->dest_type;
> + instrs[i]->texture =
> + nir_deref_as_var(nir_copy_deref(instrs[i], texture));
> + instrs[i]->sampler = NULL;
> +
> + memcpy(instrs[i]->src, srcs, instr->num_srcs * sizeof(*instr->src));
> +
> + nir_ssa_dest_init(&instrs[i]->instr, &instrs[i]->dest,
> + nir_tex_instr_dest_size(instr), 32, NULL);
> + }
> +
> + /* Fill in the last argument with the offset from the passed in offsets
> + * and insert the instruction into the stream.
> + */
> + for (uint32_t i = 0; i < 4; i++) {
> + nir_tex_src src;
> + src.src = nir_src_for_ssa(gather_offsets->elems[i]->def);
> + src.src_type = nir_tex_src_offset;
> + instrs[i]->src[instrs[i]->num_srcs - 1] = src;
> + nir_builder_instr_insert(&b->nb, &instrs[i]->instr);
> + }
> +
> + /* Combine the results of the 4 instructions by taking their .w
> + * components
> + */
> + nir_alu_instr *vec4 = nir_alu_instr_create(b->shader, nir_op_vec4);
> + nir_ssa_dest_init(&vec4->instr, &vec4->dest.dest, 4, 32, NULL);
> + vec4->dest.write_mask = 0xf;
> + for (uint32_t i = 0; i < 4; i++) {
> + vec4->src[i].src = nir_src_for_ssa(&instrs[i]->dest.ssa);
> + vec4->src[i].swizzle[0] = 3;
> + }
> + def = &vec4->dest.dest.ssa;
> + instruction = &vec4->instr;
> + } else {
> + def = &instr->dest.ssa;
> + instruction = &instr->instr;
> + }
> +
> val->ssa = vtn_create_ssa_value(b, ret_type->type);
> - val->ssa->def = &instr->dest.ssa;
> + val->ssa->def = def;
>
> - nir_builder_instr_insert(&b->nb, &instr->instr);
> + nir_builder_instr_insert(&b->nb, instruction);
> }
>
> static void
> @@ -2446,6 +2508,7 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
> case SpvCapabilityClipDistance:
> case SpvCapabilityCullDistance:
> case SpvCapabilityInputAttachment:
> + case SpvCapabilityImageGatherExtended:
> break;
>
> case SpvCapabilityGeometryStreams:
> @@ -2460,7 +2523,6 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
> case SpvCapabilityInt64Atomics:
> case SpvCapabilityAtomicStorage:
> case SpvCapabilityInt16:
> - case SpvCapabilityImageGatherExtended:
> case SpvCapabilityStorageImageMultisample:
> case SpvCapabilityImageCubeArray:
> case SpvCapabilityInt8:
> --
> 2.7.3
>
More information about the mesa-dev
mailing list