zink: add spirv builder util functions for emitting xfb decorations
[mesa.git] / src / gallium / drivers / zink / nir_to_spirv / spirv_builder.c
index 99b9e5833bc5bb0cccba275397237ea05ef0f852..4f4b790cddc0f90ee5147730aa30619c7af87703 100644 (file)
@@ -27,6 +27,8 @@
 #include "util/u_bitcast.h"
 #include "util/u_memory.h"
 #include "util/hash_table.h"
+#define XXH_INLINE_ALL
+#include "util/xxhash.h"
 
 #include <stdbool.h>
 #include <inttypes.h>
@@ -222,6 +224,37 @@ spirv_builder_emit_array_stride(struct spirv_builder *b, SpvId target,
    emit_decoration(b, target, SpvDecorationArrayStride, args, ARRAY_SIZE(args));
 }
 
+void
+spirv_builder_emit_offset(struct spirv_builder *b, SpvId target,
+                          uint32_t offset)
+{
+   uint32_t args[] = { offset };
+   emit_decoration(b, target, SpvDecorationOffset, args, ARRAY_SIZE(args));
+}
+
+void
+spirv_builder_emit_xfb_buffer(struct spirv_builder *b, SpvId target,
+                              uint32_t buffer)
+{
+   uint32_t args[] = { buffer };
+   emit_decoration(b, target, SpvDecorationXfbBuffer, args, ARRAY_SIZE(args));
+}
+
+void
+spirv_builder_emit_xfb_stride(struct spirv_builder *b, SpvId target,
+                              uint32_t stride)
+{
+   uint32_t args[] = { stride };
+   emit_decoration(b, target, SpvDecorationXfbStride, args, ARRAY_SIZE(args));
+}
+
+void
+spirv_builder_emit_index(struct spirv_builder *b, SpvId target, int index)
+{
+   uint32_t args[] = { index };
+   emit_decoration(b, target, SpvDecorationIndex, args, ARRAY_SIZE(args));
+}
+
 static void
 emit_member_decoration(struct spirv_builder *b, SpvId target, uint32_t member,
                        SpvDecoration decoration, const uint32_t extra_operands[],
@@ -513,7 +546,10 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
                                 bool proj,
                                 SpvId lod,
                                 SpvId bias,
-                                SpvId dref)
+                                SpvId dref,
+                                SpvId dx,
+                                SpvId dy,
+                                SpvId offset)
 {
    SpvId result = spirv_builder_new_id(b);
 
@@ -521,16 +557,16 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
    int operands = 5;
    if (proj)
       opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
-   if (lod)
+   if (lod || (dx && dy))
       opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
    if (dref) {
       opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;
       operands++;
    }
 
-   SpvImageOperandsMask operand_mask = 0;
-   SpvId extra_operands[3];
-   int num_extra_operands = SpvImageOperandsMaskNone;
+   SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
+   SpvId extra_operands[5];
+   int num_extra_operands = 0;
    if (bias) {
       extra_operands[++num_extra_operands] = bias;
       operand_mask |= SpvImageOperandsBiasMask;
@@ -538,6 +574,14 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
    if (lod) {
       extra_operands[++num_extra_operands] = lod;
       operand_mask |= SpvImageOperandsLodMask;
+   } else if (dx && dy) {
+      extra_operands[++num_extra_operands] = dx;
+      extra_operands[++num_extra_operands] = dy;
+      operand_mask |= SpvImageOperandsGradMask;
+   }
+   if (offset) {
+      extra_operands[++num_extra_operands] = offset;
+      operand_mask |= SpvImageOperandsOffsetMask;
    }
 
    /* finalize num_extra_operands / extra_operands */
@@ -559,6 +603,85 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
    return result;
 }
 
+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 sample)
+{
+   SpvId result = spirv_builder_new_id(b);
+
+   SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
+   SpvId extra_operands[3];
+   int num_extra_operands = 0;
+   if (lod) {
+      extra_operands[++num_extra_operands] = lod;
+      operand_mask |= SpvImageOperandsLodMask;
+   }
+   if (sample) {
+      extra_operands[++num_extra_operands] = sample;
+      operand_mask |= SpvImageOperandsSampleMask;
+   }
+
+   /* finalize num_extra_operands / extra_operands */
+   if (num_extra_operands > 0) {
+      extra_operands[0] = operand_mask;
+      num_extra_operands++;
+   }
+
+   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_image_query_size(struct spirv_builder *b,
+                                    SpvId result_type,
+                                    SpvId image,
+                                    SpvId lod)
+{
+   int opcode = SpvOpImageQuerySize;
+   int words = 4;
+   if (lod) {
+      words++;
+      opcode = SpvOpImageQuerySizeLod;
+   }
+
+   SpvId result = spirv_builder_new_id(b);
+   spirv_buffer_prepare(&b->instructions, words);
+   spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));
+   spirv_buffer_emit_word(&b->instructions, result_type);
+   spirv_buffer_emit_word(&b->instructions, result);
+   spirv_buffer_emit_word(&b->instructions, image);
+
+   if (lod)
+      spirv_buffer_emit_word(&b->instructions, lod);
+
+   return result;
+}
+
 SpvId
 spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
                             SpvId set, uint32_t instruction,
@@ -591,10 +714,9 @@ non_aggregate_type_hash(const void *arg)
 {
    const struct spirv_type *type = arg;
 
-   uint32_t hash = _mesa_fnv32_1a_offset_bias;
-   hash = _mesa_fnv32_1a_accumulate(hash, type->op);
-   hash = _mesa_fnv32_1a_accumulate_block(hash, type->args, sizeof(uint32_t) *
-                                          type->num_args);
+   uint32_t hash = 0;
+   hash = XXH32(&type->op, sizeof(type->op), hash);
+   hash = XXH32(type->args, sizeof(uint32_t) * type->num_args, hash);
    return hash;
 }
 
@@ -797,11 +919,10 @@ const_hash(const void *arg)
 {
    const struct spirv_const *key = arg;
 
-   uint32_t hash = _mesa_fnv32_1a_offset_bias;
-   hash = _mesa_fnv32_1a_accumulate(hash, key->op);
-   hash = _mesa_fnv32_1a_accumulate(hash, key->type);
-   hash = _mesa_fnv32_1a_accumulate_block(hash, key->args, sizeof(uint32_t) *
-                                          key->num_args);
+   uint32_t hash = 0;
+   hash = XXH32(&key->op, sizeof(key->op), hash);
+   hash = XXH32(&key->type, sizeof(key->type), hash);
+   hash = XXH32(key->args, sizeof(uint32_t) * key->num_args, hash);
    return hash;
 }
 
@@ -840,7 +961,7 @@ get_const_def(struct spirv_builder *b, SpvOp op, SpvId type,
    }
 
    struct spirv_const *cnst = CALLOC_STRUCT(spirv_const);
-   if (!type)
+   if (!cnst)
       return 0;
 
    cnst->op = op;