summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2016-01-12 16:28:28 -0800
committerJason Ekstrand <[email protected]>2016-01-13 15:18:36 -0800
commitc95c3b2c213137e807522d132e06c841f33bfd25 (patch)
tree033d84c7a0e65305bb5f0bdebdfe6237e7567a8b
parent610aa00cdf54cf7c0bb31c54bc87580d66cd3d14 (diff)
nir/spirv: Add initial support for specialization constants
-rw-r--r--src/glsl/nir/spirv/nir_spirv.h7
-rw-r--r--src/glsl/nir/spirv/spirv_to_nir.c46
-rw-r--r--src/glsl/nir/spirv/vtn_private.h3
-rw-r--r--src/glsl/nir/spirv2nir.c4
-rw-r--r--src/vulkan/anv_pipeline.c2
5 files changed, 59 insertions, 3 deletions
diff --git a/src/glsl/nir/spirv/nir_spirv.h b/src/glsl/nir/spirv/nir_spirv.h
index 354c0a902df..9c9c93d36c2 100644
--- a/src/glsl/nir/spirv/nir_spirv.h
+++ b/src/glsl/nir/spirv/nir_spirv.h
@@ -36,7 +36,14 @@
extern "C" {
#endif
+struct nir_spirv_specialization {
+ uint32_t id;
+ uint32_t data;
+};
+
nir_function *spirv_to_nir(const uint32_t *words, size_t word_count,
+ struct nir_spirv_specialization *specializations,
+ unsigned num_specializations,
gl_shader_stage stage, const char *entry_point_name,
const nir_shader_compiler_options *options);
diff --git a/src/glsl/nir/spirv/spirv_to_nir.c b/src/glsl/nir/spirv/spirv_to_nir.c
index bbde4554c6b..deea1adb3ea 100644
--- a/src/glsl/nir/spirv/spirv_to_nir.c
+++ b/src/glsl/nir/spirv/spirv_to_nir.c
@@ -805,6 +805,33 @@ vtn_null_constant(struct vtn_builder *b, const struct glsl_type *type)
}
static void
+spec_constant_deocoration_cb(struct vtn_builder *b, struct vtn_value *v,
+ int member, const struct vtn_decoration *dec,
+ void *data)
+{
+ assert(member == -1);
+ if (dec->decoration != SpvDecorationSpecId)
+ return;
+
+ uint32_t *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;
+ return;
+ }
+ }
+}
+
+static uint32_t
+get_specialization(struct vtn_builder *b, struct vtn_value *val,
+ uint32_t const_value)
+{
+ vtn_foreach_decoration(b, val, spec_constant_deocoration_cb, &const_value);
+ return const_value;
+}
+
+static void
vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
{
@@ -820,10 +847,25 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
assert(val->const_type == glsl_bool_type());
val->constant->value.u[0] = NIR_FALSE;
break;
+
+ case SpvOpSpecConstantTrue:
+ case SpvOpSpecConstantFalse: {
+ assert(val->const_type == glsl_bool_type());
+ uint32_t int_val =
+ get_specialization(b, val, (opcode == SpvOpSpecConstantTrue));
+ val->constant->value.u[0] = int_val ? NIR_TRUE : NIR_FALSE;
+ break;
+ }
+
case SpvOpConstant:
assert(glsl_type_is_scalar(val->const_type));
val->constant->value.u[0] = w[3];
break;
+ case SpvOpSpecConstant:
+ assert(glsl_type_is_scalar(val->const_type));
+ val->constant->value.u[0] = get_specialization(b, val, w[3]);
+ break;
+ case SpvOpSpecConstantComposite:
case SpvOpConstantComposite: {
unsigned elem_count = count - 3;
nir_constant **elems = ralloc_array(b, nir_constant *, elem_count);
@@ -3493,6 +3535,7 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
nir_function *
spirv_to_nir(const uint32_t *words, size_t word_count,
+ struct nir_spirv_specialization *spec, unsigned num_spec,
gl_shader_stage stage, const char *entry_point_name,
const nir_shader_compiler_options *options)
{
@@ -3533,6 +3576,9 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
vtn_foreach_execution_mode(b, b->entry_point,
vtn_handle_execution_mode, NULL);
+ b->specializations = spec;
+ b->num_specializations = num_spec;
+
/* Handle all variable, type, and constant instructions */
words = vtn_foreach_instruction(b, words, word_end,
vtn_handle_variable_or_type_instruction);
diff --git a/src/glsl/nir/spirv/vtn_private.h b/src/glsl/nir/spirv/vtn_private.h
index 7ab3c9fba4c..1f88eeda941 100644
--- a/src/glsl/nir/spirv/vtn_private.h
+++ b/src/glsl/nir/spirv/vtn_private.h
@@ -310,6 +310,9 @@ struct vtn_builder {
*/
struct hash_table *phi_table;
+ unsigned num_specializations;
+ struct nir_spirv_specialization *specializations;
+
/*
* NIR variable for each SPIR-V builtin.
*/
diff --git a/src/glsl/nir/spirv2nir.c b/src/glsl/nir/spirv2nir.c
index 4cb484cd074..c837186bdfc 100644
--- a/src/glsl/nir/spirv2nir.c
+++ b/src/glsl/nir/spirv2nir.c
@@ -49,7 +49,7 @@ int main(int argc, char **argv)
const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
assert(map != NULL);
- nir_function *func = spirv_to_nir(map, word_count, MESA_SHADER_FRAGMENT,
- "main", NULL);
+ nir_function *func = spirv_to_nir(map, word_count, NULL, 0,
+ MESA_SHADER_FRAGMENT, "main", NULL);
nir_print_shader(func->shader, stderr);
}
diff --git a/src/vulkan/anv_pipeline.c b/src/vulkan/anv_pipeline.c
index db4e19bf486..3d632dec038 100644
--- a/src/vulkan/anv_pipeline.c
+++ b/src/vulkan/anv_pipeline.c
@@ -113,7 +113,7 @@ anv_shader_compile_to_nir(struct anv_device *device,
assert(spirv[0] == SPIR_V_MAGIC_NUMBER);
assert(module->size % 4 == 0);
- entry_point = spirv_to_nir(spirv, module->size / 4, stage,
+ entry_point = spirv_to_nir(spirv, module->size / 4, NULL, 0, stage,
entrypoint_name, nir_options);
nir = entry_point->shader;
assert(nir->stage == stage);