spirv: add support for doubles to OpSpecConstant
authorSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Mon, 14 Nov 2016 11:08:32 +0000 (12:08 +0100)
committerSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Mon, 9 Jan 2017 08:10:13 +0000 (09:10 +0100)
v2 (Jason):
- Fix indent in radv change
- Add vtn_u64_literal() helper to take 64 bits (Jason)

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/amd/vulkan/radv_pipeline.c
src/compiler/spirv/nir_spirv.h
src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_private.h
src/intel/vulkan/anv_pipeline.c

index 75785ec921d040ff59869fada72ed879f53b4a37..efb9cacf924839991f054719efc81f851c41fb8d 100644 (file)
@@ -188,7 +188,10 @@ radv_shader_compile_to_nir(struct radv_device *device,
                                assert(data + entry.size <= spec_info->pData + spec_info->dataSize);
 
                                spec_entries[i].id = spec_info->pMapEntries[i].constantID;
-                               spec_entries[i].data = *(const uint32_t *)data;
+                               if (spec_info->dataSize == 8)
+                                       spec_entries[i].data64 = *(const uint64_t *)data;
+                               else
+                                       spec_entries[i].data32 = *(const uint32_t *)data;
                        }
                }
                const struct nir_spirv_supported_extensions supported_ext = {
index e0112ef4ad4786e52967863497c18f350986b1bb..116b0a374cd64f300819308642c822b20fea0bb8 100644 (file)
@@ -38,7 +38,10 @@ extern "C" {
 
 struct nir_spirv_specialization {
    uint32_t id;
-   uint32_t data;
+   union {
+      uint32_t data32;
+      uint64_t data64;
+   };
 };
 
 struct nir_spirv_supported_extensions {
index f203ebc7ef7bf9e970c516849e1c331595ce1c05..b67189e07a68ca29ad2e599fb69b92ecd508a766 100644 (file)
 #include "nir/nir_constant_expressions.h"
 #include "spirv_info.h"
 
+struct spec_constant_value {
+   bool is_double;
+   union {
+      uint32_t data32;
+      uint64_t data64;
+   };
+};
+
 void
 _vtn_warn(const char *file, int line, const char *msg, ...)
 {
@@ -942,11 +950,14 @@ spec_constant_decoration_cb(struct vtn_builder *b, struct vtn_value *v,
    if (dec->decoration != SpvDecorationSpecId)
       return;
 
-   uint32_t *const_value = data;
+   struct spec_constant_value *const_value = data;
 
    for (unsigned i = 0; i < b->num_specializations; i++) {
       if (b->specializations[i].id == dec->literals[0]) {
-         *const_value = b->specializations[i].data;
+         if (const_value->is_double)
+            const_value->data64 = b->specializations[i].data64;
+         else
+            const_value->data32 = b->specializations[i].data32;
          return;
       }
    }
@@ -956,8 +967,22 @@ static uint32_t
 get_specialization(struct vtn_builder *b, struct vtn_value *val,
                    uint32_t const_value)
 {
-   vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &const_value);
-   return const_value;
+   struct spec_constant_value data;
+   data.is_double = false;
+   data.data32 = const_value;
+   vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &data);
+   return data.data32;
+}
+
+static uint64_t
+get_specialization64(struct vtn_builder *b, struct vtn_value *val,
+                   uint64_t const_value)
+{
+   struct spec_constant_value data;
+   data.is_double = true;
+   data.data64 = const_value;
+   vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &data);
+   return data.data64;
 }
 
 static void
@@ -1017,10 +1042,17 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
       }
       break;
    }
-   case SpvOpSpecConstant:
+   case SpvOpSpecConstant: {
       assert(glsl_type_is_scalar(val->const_type));
       val->constant->values[0].u32[0] = get_specialization(b, val, w[3]);
+      int bit_size = glsl_get_bit_size(val->const_type);
+      if (bit_size == 64)
+         val->constant->values[0].u64[0] =
+            get_specialization64(b, val, vtn_u64_literal(&w[3]));
+      else
+         val->constant->values[0].u32[0] = get_specialization(b, val, w[3]);
       break;
+   }
    case SpvOpSpecConstantComposite:
    case SpvOpConstantComposite: {
       unsigned elem_count = count - 3;
index ffa00d7f68ac34f62940f643ec56ae5105b6dd04..7471ca1e21a1e25233e7b94682af70d50f2f547d 100644 (file)
@@ -489,3 +489,9 @@ void vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
 
 bool vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
                                     const uint32_t *words, unsigned count);
+
+static inline uint64_t
+vtn_u64_literal(const uint32_t *w)
+{
+   return (uint64_t)w[1] << 32 | w[0];
+}
index 17491e34fc022950e7bab2818725de66a11f88ae..d5a7406c66c0da7144cfe7b7bbfb5fbce0dcbd56 100644 (file)
@@ -117,7 +117,10 @@ anv_shader_compile_to_nir(struct anv_device *device,
          assert(data + entry.size <= spec_info->pData + spec_info->dataSize);
 
          spec_entries[i].id = spec_info->pMapEntries[i].constantID;
-         spec_entries[i].data = *(const uint32_t *)data;
+         if (spec_info->dataSize == 8)
+            spec_entries[i].data64 = *(const uint64_t *)data;
+         else
+            spec_entries[i].data32 = *(const uint32_t *)data;
       }
    }