summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorCaio Marcelo de Oliveira Filho <[email protected]>2019-10-22 23:37:18 -0700
committerCaio Marcelo de Oliveira Filho <[email protected]>2019-10-24 11:39:56 -0700
commitd31f415ba0fd4842a5def2512d07b370c3139006 (patch)
treedf3cbbadfc59d69ea7102e5006b8727056141f5f /src/compiler
parentc7d8fe2f0d23a82ed92a58594645c227155c35f0 (diff)
spirv: Add helper to find args of Image Operands
Avoid keeping track of the idx and all possible image operands for each operation. Note for convenience we split up the handling of ImageOperandsOffsetMask and ImageOperandsConstOffsetMask. Suggested by Jason Ekstrand. Reviewed-by: Jason Ekstrand <[email protected]> Reviewed-by: Bas Nieuwenhuizen <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/spirv/spirv_to_nir.c101
1 files changed, 79 insertions, 22 deletions
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index d1884f48330..e436f28de60 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -2181,6 +2181,42 @@ vtn_tex_src(struct vtn_builder *b, unsigned index, nir_tex_src_type type)
return src;
}
+static uint32_t
+image_operand_arg(struct vtn_builder *b, const uint32_t *w, uint32_t count,
+ uint32_t mask_idx, SpvImageOperandsMask op)
+{
+ static const SpvImageOperandsMask ops_with_arg =
+ SpvImageOperandsBiasMask |
+ SpvImageOperandsLodMask |
+ SpvImageOperandsGradMask |
+ SpvImageOperandsConstOffsetMask |
+ SpvImageOperandsOffsetMask |
+ SpvImageOperandsConstOffsetsMask |
+ SpvImageOperandsSampleMask |
+ SpvImageOperandsMinLodMask |
+ SpvImageOperandsMakeTexelAvailableMask |
+ SpvImageOperandsMakeTexelVisibleMask;
+
+ assert(util_bitcount(op) == 1);
+ assert(w[mask_idx] & op);
+ assert(op & ops_with_arg);
+
+ uint32_t idx = util_bitcount(w[mask_idx] & (op - 1) & ops_with_arg) + 1;
+
+ /* Adjust indices for operands with two arguments. */
+ static const SpvImageOperandsMask ops_with_two_args =
+ SpvImageOperandsGradMask;
+ idx += util_bitcount(w[mask_idx] & (op - 1) & ops_with_two_args);
+
+ idx += mask_idx;
+
+ vtn_fail_if(idx + (op & ops_with_two_args ? 1 : 0) >= count,
+ "Image op claims to have %s but does not enough "
+ "following operands", spirv_imageoperands_to_string(op));
+
+ return idx;
+}
+
static void
vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
@@ -2417,25 +2453,31 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
/* Now we need to handle some number of optional arguments */
struct vtn_value *gather_offsets = NULL;
if (idx < count) {
- uint32_t operands = w[idx++];
+ uint32_t operands = w[idx];
if (operands & SpvImageOperandsBiasMask) {
vtn_assert(texop == nir_texop_tex);
texop = nir_texop_txb;
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_bias);
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsBiasMask);
+ (*p++) = vtn_tex_src(b, w[arg], nir_tex_src_bias);
}
if (operands & SpvImageOperandsLodMask) {
vtn_assert(texop == nir_texop_txl || texop == nir_texop_txf ||
texop == nir_texop_txs);
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod);
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsLodMask);
+ (*p++) = vtn_tex_src(b, w[arg], nir_tex_src_lod);
}
if (operands & SpvImageOperandsGradMask) {
vtn_assert(texop == nir_texop_txl);
texop = nir_texop_txd;
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ddx);
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ddy);
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsGradMask);
+ (*p++) = vtn_tex_src(b, w[arg], nir_tex_src_ddx);
+ (*p++) = vtn_tex_src(b, w[arg + 1], nir_tex_src_ddy);
}
vtn_fail_if(util_bitcount(operands & (SpvImageOperandsConstOffsetsMask |
@@ -2444,30 +2486,42 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
"At most one of the ConstOffset, Offset, and ConstOffsets "
"image operands can be used on a given instruction.");
- if (operands & SpvImageOperandsOffsetMask ||
- operands & SpvImageOperandsConstOffsetMask)
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_offset);
+ if (operands & SpvImageOperandsOffsetMask) {
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsOffsetMask);
+ (*p++) = vtn_tex_src(b, w[arg], nir_tex_src_offset);
+ }
+
+ if (operands & SpvImageOperandsConstOffsetMask) {
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsConstOffsetMask);
+ (*p++) = vtn_tex_src(b, w[arg], nir_tex_src_offset);
+ }
if (operands & SpvImageOperandsConstOffsetsMask) {
vtn_assert(texop == nir_texop_tg4);
- gather_offsets = vtn_value(b, w[idx++], vtn_value_type_constant);
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsConstOffsetsMask);
+ gather_offsets = vtn_value(b, w[arg], vtn_value_type_constant);
}
if (operands & SpvImageOperandsSampleMask) {
vtn_assert(texop == nir_texop_txf_ms);
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsSampleMask);
texop = nir_texop_txf_ms;
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ms_index);
+ (*p++) = vtn_tex_src(b, w[arg], nir_tex_src_ms_index);
}
if (operands & SpvImageOperandsMinLodMask) {
vtn_assert(texop == nir_texop_tex ||
texop == nir_texop_txb ||
texop == nir_texop_txd);
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_min_lod);
+ uint32_t arg = image_operand_arg(b, w, count, idx,
+ SpvImageOperandsMinLodMask);
+ (*p++) = vtn_tex_src(b, w[arg], nir_tex_src_min_lod);
}
}
- /* We should have now consumed exactly all of the arguments */
- vtn_assert(idx == count);
nir_tex_instr *instr = nir_tex_instr_create(b->shader, p - srcs);
instr->op = texop;
@@ -2672,10 +2726,10 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
const SpvImageOperandsMask operands =
count > 5 ? w[5] : SpvImageOperandsMaskNone;
- int idx = 6;
if (operands & SpvImageOperandsSampleMask) {
- image.sample = vtn_ssa_value(b, w[idx])->def;
- idx++;
+ uint32_t arg = image_operand_arg(b, w, count, 5,
+ SpvImageOperandsSampleMask);
+ image.sample = vtn_ssa_value(b, w[arg])->def;
} else {
image.sample = nir_ssa_undef(&b->nb, 1, 32);
}
@@ -2683,9 +2737,10 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
if (operands & SpvImageOperandsMakeTexelVisibleMask) {
vtn_fail_if((operands & SpvImageOperandsNonPrivateTexelMask) == 0,
"MakeTexelVisible requires NonPrivateTexel to also be set.");
+ uint32_t arg = image_operand_arg(b, w, count, 5,
+ SpvImageOperandsMakeTexelVisibleMask);
semantics = SpvMemorySemanticsMakeVisibleMask;
- scope = vtn_constant_uint(b, w[idx]);
- idx++;
+ scope = vtn_constant_uint(b, w[arg]);
}
/* TODO: Volatile. */
@@ -2702,10 +2757,10 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
const SpvImageOperandsMask operands =
count > 4 ? w[4] : SpvImageOperandsMaskNone;
- int idx = 5;
if (operands & SpvImageOperandsSampleMask) {
- image.sample = vtn_ssa_value(b, w[idx])->def;
- idx++;
+ uint32_t arg = image_operand_arg(b, w, count, 4,
+ SpvImageOperandsSampleMask);
+ image.sample = vtn_ssa_value(b, w[arg])->def;
} else {
image.sample = nir_ssa_undef(&b->nb, 1, 32);
}
@@ -2713,8 +2768,10 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
if (operands & SpvImageOperandsMakeTexelAvailableMask) {
vtn_fail_if((operands & SpvImageOperandsNonPrivateTexelMask) == 0,
"MakeTexelAvailable requires NonPrivateTexel to also be set.");
+ uint32_t arg = image_operand_arg(b, w, count, 4,
+ SpvImageOperandsMakeTexelAvailableMask);
semantics = SpvMemorySemanticsMakeAvailableMask;
- scope = vtn_constant_uint(b, w[idx]);
+ scope = vtn_constant_uint(b, w[arg]);
}
/* TODO: Volatile. */