summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c40
-rw-r--r--src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c42
-rw-r--r--src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h11
3 files changed, 85 insertions, 8 deletions
diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
index e11882348cb..e027058628e 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
+++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
@@ -1319,13 +1319,23 @@ get_src_float(struct ntv_context *ctx, nir_src *src)
return bitcast_to_fvec(ctx, def, bit_size, num_components);
}
+static SpvId
+get_src_int(struct ntv_context *ctx, nir_src *src)
+{
+ SpvId def = get_src_uint(ctx, src);
+ unsigned num_components = nir_src_num_components(*src);
+ unsigned bit_size = nir_src_bit_size(*src);
+ return bitcast_to_ivec(ctx, def, bit_size, num_components);
+}
+
static void
emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
{
assert(tex->op == nir_texop_tex ||
tex->op == nir_texop_txb ||
tex->op == nir_texop_txl ||
- tex->op == nir_texop_txd);
+ tex->op == nir_texop_txd ||
+ tex->op == nir_texop_txf);
assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
assert(tex->texture_index == tex->sampler_index);
@@ -1334,7 +1344,10 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
for (unsigned i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
case nir_tex_src_coord:
- coord = get_src_float(ctx, &tex->src[i].src);
+ if (tex->op == nir_texop_txf)
+ coord = get_src_int(ctx, &tex->src[i].src);
+ else
+ coord = get_src_float(ctx, &tex->src[i].src);
coord_components = nir_src_num_components(tex->src[i].src);
break;
@@ -1352,7 +1365,10 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
case nir_tex_src_lod:
assert(nir_src_num_components(tex->src[i].src) == 1);
- lod = get_src_float(ctx, &tex->src[i].src);
+ if (tex->op == nir_texop_txf)
+ lod = get_src_int(ctx, &tex->src[i].src);
+ else
+ lod = get_src_float(ctx, &tex->src[i].src);
assert(lod != 0);
break;
@@ -1425,11 +1441,19 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
if (dref)
actual_dest_type = float_type;
- SpvId result = spirv_builder_emit_image_sample(&ctx->builder,
- actual_dest_type, load,
- coord,
- proj != 0,
- lod, bias, dref, dx, dy);
+ SpvId result;
+ if (tex->op == nir_texop_txf) {
+ SpvId image = spirv_builder_emit_image(&ctx->builder, image_type, load);
+ result = spirv_builder_emit_image_fetch(&ctx->builder, dest_type,
+ image, coord, lod);
+ } else {
+ result = spirv_builder_emit_image_sample(&ctx->builder,
+ actual_dest_type, load,
+ coord,
+ proj != 0,
+ lod, bias, dref, dx, dy);
+ }
+
spirv_builder_emit_decoration(&ctx->builder, result,
SpvDecorationRelaxedPrecision);
diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
index 275f81eb4fb..43a4a556653 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
+++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
@@ -566,6 +566,48 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
}
SpvId
+spirv_builder_emit_image(struct spirv_builder *b, SpvId result_type,
+ SpvId sampled_image)
+{
+ SpvId result = spirv_builder_new_id(b);
+ spirv_buffer_prepare(&b->instructions, 4);
+ spirv_buffer_emit_word(&b->instructions, SpvOpImage | (4 << 16));
+ spirv_buffer_emit_word(&b->instructions, result_type);
+ spirv_buffer_emit_word(&b->instructions, result);
+ spirv_buffer_emit_word(&b->instructions, sampled_image);
+ return result;
+}
+
+SpvId
+spirv_builder_emit_image_fetch(struct spirv_builder *b,
+ SpvId result_type,
+ SpvId image,
+ SpvId coordinate,
+ SpvId lod)
+{
+ SpvId result = spirv_builder_new_id(b);
+
+ SpvId extra_operands[2];
+ int num_extra_operands = 0;
+ if (lod) {
+ extra_operands[0] = SpvImageOperandsLodMask;
+ extra_operands[1] = lod;
+ num_extra_operands = 2;
+ }
+
+ spirv_buffer_prepare(&b->instructions, 5 + num_extra_operands);
+ spirv_buffer_emit_word(&b->instructions, SpvOpImageFetch |
+ ((5 + num_extra_operands) << 16));
+ spirv_buffer_emit_word(&b->instructions, result_type);
+ spirv_buffer_emit_word(&b->instructions, result);
+ spirv_buffer_emit_word(&b->instructions, image);
+ spirv_buffer_emit_word(&b->instructions, coordinate);
+ for (int i = 0; i < num_extra_operands; ++i)
+ spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
+ return result;
+}
+
+SpvId
spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
SpvId set, uint32_t instruction,
const SpvId *args, size_t num_args)
diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
index 736eb211fc7..d7213d85f65 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
+++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
@@ -218,6 +218,17 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
SpvId dy);
SpvId
+spirv_builder_emit_image(struct spirv_builder *b, SpvId result_type,
+ SpvId sampled_image);
+
+SpvId
+spirv_builder_emit_image_fetch(struct spirv_builder *b,
+ SpvId result_type,
+ SpvId image,
+ SpvId coordinate,
+ SpvId lod);
+
+SpvId
spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
SpvId set, uint32_t instruction,
const SpvId args[], size_t num_args);