Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2014-2015 Broadcom
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  */
  23.  
  24. #ifndef NIR_BUILDER_H
  25. #define NIR_BUILDER_H
  26.  
  27. struct exec_list;
  28.  
  29. typedef struct nir_builder {
  30.    struct exec_list *cf_node_list;
  31.    nir_instr *before_instr;
  32.    nir_instr *after_instr;
  33.  
  34.    nir_shader *shader;
  35.    nir_function_impl *impl;
  36. } nir_builder;
  37.  
  38. static inline void
  39. nir_builder_init(nir_builder *build, nir_function_impl *impl)
  40. {
  41.    memset(build, 0, sizeof(*build));
  42.    build->impl = impl;
  43.    build->shader = impl->overload->function->shader;
  44. }
  45.  
  46. static inline void
  47. nir_builder_insert_after_cf_list(nir_builder *build,
  48.                                  struct exec_list *cf_node_list)
  49. {
  50.    build->cf_node_list = cf_node_list;
  51.    build->before_instr = NULL;
  52.    build->after_instr = NULL;
  53. }
  54.  
  55. static inline void
  56. nir_builder_insert_before_instr(nir_builder *build, nir_instr *before_instr)
  57. {
  58.    build->cf_node_list = NULL;
  59.    build->before_instr = before_instr;
  60.    build->after_instr = NULL;
  61. }
  62.  
  63. static inline void
  64. nir_builder_insert_after_instr(nir_builder *build, nir_instr *after_instr)
  65. {
  66.    build->cf_node_list = NULL;
  67.    build->before_instr = NULL;
  68.    build->after_instr = after_instr;
  69. }
  70.  
  71. static inline void
  72. nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
  73. {
  74.    if (build->cf_node_list) {
  75.       nir_instr_insert_after_cf_list(build->cf_node_list, instr);
  76.    } else if (build->before_instr) {
  77.       nir_instr_insert_before(build->before_instr, instr);
  78.    } else {
  79.       assert(build->after_instr);
  80.       nir_instr_insert_after(build->after_instr, instr);
  81.       build->after_instr = instr;
  82.    }
  83. }
  84.  
  85. static inline nir_ssa_def *
  86. nir_build_imm(nir_builder *build, unsigned num_components, nir_const_value value)
  87. {
  88.    nir_load_const_instr *load_const =
  89.       nir_load_const_instr_create(build->shader, num_components);
  90.    if (!load_const)
  91.       return NULL;
  92.  
  93.    load_const->value = value;
  94.  
  95.    nir_builder_instr_insert(build, &load_const->instr);
  96.  
  97.    return &load_const->def;
  98. }
  99.  
  100. static inline nir_ssa_def *
  101. nir_imm_float(nir_builder *build, float x)
  102. {
  103.    nir_const_value v = { { .f = {x, 0, 0, 0} } };
  104.    return nir_build_imm(build, 1, v);
  105. }
  106.  
  107. static inline nir_ssa_def *
  108. nir_imm_vec4(nir_builder *build, float x, float y, float z, float w)
  109. {
  110.    nir_const_value v = { { .f = {x, y, z, w} } };
  111.    return nir_build_imm(build, 4, v);
  112. }
  113.  
  114. static inline nir_ssa_def *
  115. nir_imm_int(nir_builder *build, int x)
  116. {
  117.    nir_const_value v = { { .i = {x, 0, 0, 0} } };
  118.    return nir_build_imm(build, 1, v);
  119. }
  120.  
  121. static inline nir_ssa_def *
  122. nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
  123.               nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)
  124. {
  125.    const nir_op_info *op_info = &nir_op_infos[op];
  126.    nir_alu_instr *instr = nir_alu_instr_create(build->shader, op);
  127.    if (!instr)
  128.       return NULL;
  129.  
  130.    instr->src[0].src = nir_src_for_ssa(src0);
  131.    if (src1)
  132.       instr->src[1].src = nir_src_for_ssa(src1);
  133.    if (src2)
  134.       instr->src[2].src = nir_src_for_ssa(src2);
  135.    if (src3)
  136.       instr->src[3].src = nir_src_for_ssa(src3);
  137.  
  138.    /* Guess the number of components the destination temporary should have
  139.     * based on our input sizes, if it's not fixed for the op.
  140.     */
  141.    unsigned num_components = op_info->output_size;
  142.    if (num_components == 0) {
  143.       for (unsigned i = 0; i < op_info->num_inputs; i++) {
  144.          if (op_info->input_sizes[i] == 0)
  145.             num_components = MAX2(num_components,
  146.                                   instr->src[i].src.ssa->num_components);
  147.       }
  148.    }
  149.    assert(num_components != 0);
  150.  
  151.    /* Make sure we don't swizzle from outside of our source vector (like if a
  152.     * scalar value was passed into a multiply with a vector).
  153.     */
  154.    for (unsigned i = 0; i < op_info->num_inputs; i++) {
  155.       for (unsigned j = instr->src[i].src.ssa->num_components; j < 4; j++) {
  156.          instr->src[i].swizzle[j] = instr->src[i].src.ssa->num_components - 1;
  157.       }
  158.    }
  159.  
  160.    nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL);
  161.    instr->dest.write_mask = (1 << num_components) - 1;
  162.  
  163.    nir_builder_instr_insert(build, &instr->instr);
  164.  
  165.    return &instr->dest.dest.ssa;
  166. }
  167.  
  168. #define ALU1(op)                                                          \
  169. static inline nir_ssa_def *                                               \
  170. nir_##op(nir_builder *build, nir_ssa_def *src0)                           \
  171. {                                                                         \
  172.    return nir_build_alu(build, nir_op_##op, src0, NULL, NULL, NULL);      \
  173. }
  174.  
  175. #define ALU2(op)                                                          \
  176. static inline nir_ssa_def *                                               \
  177. nir_##op(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1)        \
  178. {                                                                         \
  179.    return nir_build_alu(build, nir_op_##op, src0, src1, NULL, NULL);      \
  180. }
  181.  
  182. #define ALU3(op)                                                          \
  183. static inline nir_ssa_def *                                               \
  184. nir_##op(nir_builder *build, nir_ssa_def *src0,                           \
  185.          nir_ssa_def *src1, nir_ssa_def *src2)                            \
  186. {                                                                         \
  187.    return nir_build_alu(build, nir_op_##op, src0, src1, src2, NULL);      \
  188. }
  189.  
  190. #define ALU4(op)                                                          \
  191. static inline nir_ssa_def *                                               \
  192. nir_##op(nir_builder *build, nir_ssa_def *src0,                           \
  193.          nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)         \
  194. {                                                                         \
  195.    return nir_build_alu(build, nir_op_##op, src0, src1, src2, src3);      \
  196. }
  197.  
  198. #include "nir_builder_opcodes.h"
  199.  
  200. /**
  201.  * Similar to nir_fmov, but takes a nir_alu_src instead of a nir_ssa_def.
  202.  */
  203. static inline nir_ssa_def *
  204. nir_fmov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
  205. {
  206.    nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_fmov);
  207.    nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
  208.    mov->dest.write_mask = (1 << num_components) - 1;
  209.    mov->src[0] = src;
  210.    nir_builder_instr_insert(build, &mov->instr);
  211.  
  212.    return &mov->dest.dest.ssa;
  213. }
  214.  
  215. static inline nir_ssa_def *
  216. nir_imov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
  217. {
  218.    nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_imov);
  219.    nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
  220.    mov->dest.write_mask = (1 << num_components) - 1;
  221.    mov->src[0] = src;
  222.    nir_builder_instr_insert(build, &mov->instr);
  223.  
  224.    return &mov->dest.dest.ssa;
  225. }
  226.  
  227. /**
  228.  * Construct an fmov or imov that reswizzles the source's components.
  229.  */
  230. static inline nir_ssa_def *
  231. nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
  232.             unsigned num_components, bool use_fmov)
  233. {
  234.    nir_alu_src alu_src = { NIR_SRC_INIT };
  235.    alu_src.src = nir_src_for_ssa(src);
  236.    for (int i = 0; i < 4; i++)
  237.       alu_src.swizzle[i] = swiz[i];
  238.  
  239.    return use_fmov ? nir_fmov_alu(build, alu_src, num_components) :
  240.                      nir_imov_alu(build, alu_src, num_components);
  241. }
  242.  
  243. /**
  244.  * Turns a nir_src into a nir_ssa_def * so it can be passed to
  245.  * nir_build_alu()-based builder calls.
  246.  */
  247. static inline nir_ssa_def *
  248. nir_ssa_for_src(nir_builder *build, nir_src src, int num_components)
  249. {
  250.    if (src.is_ssa && src.ssa->num_components == num_components)
  251.       return src.ssa;
  252.  
  253.    nir_alu_src alu = { NIR_SRC_INIT };
  254.    alu.src = src;
  255.    for (int j = 0; j < 4; j++)
  256.       alu.swizzle[j] = j;
  257.  
  258.    return nir_imov_alu(build, alu, num_components);
  259. }
  260.  
  261. #endif /* NIR_BUILDER_H */
  262.