Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2015 Intel Corporation
  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.  * Authors:
  24.  *    Jason Ekstrand <jason@jlekstrand.net>
  25.  */
  26.  
  27. #include "nir.h"
  28. #include "nir_builder.h"
  29.  
  30. /**
  31.  * This file implements a NIR lowering pass to perform the normalization of
  32.  * the cubemap coordinates to have the largest magnitude component be -1.0
  33.  * or 1.0.  This is based on the old GLSL IR based pass by Eric.
  34.  */
  35.  
  36. static nir_ssa_def *
  37. channel(nir_builder *b, nir_ssa_def *def, int c)
  38. {
  39.    return nir_swizzle(b, def, (unsigned[4]){c, c, c, c}, 1, false);
  40. }
  41.  
  42. static bool
  43. normalize_cubemap_coords_block(nir_block *block, void *void_state)
  44. {
  45.    nir_builder *b = void_state;
  46.  
  47.    nir_foreach_instr(block, instr) {
  48.       if (instr->type != nir_instr_type_tex)
  49.          continue;
  50.  
  51.       nir_tex_instr *tex = nir_instr_as_tex(instr);
  52.       if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE)
  53.          continue;
  54.  
  55.       nir_builder_insert_before_instr(b, &tex->instr);
  56.  
  57.       for (unsigned i = 0; i < tex->num_srcs; i++) {
  58.          if (tex->src[i].src_type != nir_tex_src_coord)
  59.             continue;
  60.  
  61.          nir_ssa_def *orig_coord =
  62.             nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
  63.          assert(orig_coord->num_components >= 3);
  64.  
  65.          nir_ssa_def *abs = nir_fabs(b, orig_coord);
  66.          nir_ssa_def *norm = nir_fmax(b, channel(b, abs, 0),
  67.                                          nir_fmax(b, channel(b, abs, 1),
  68.                                                      channel(b, abs, 2)));
  69.  
  70.          nir_ssa_def *normalized = nir_fmul(b, orig_coord, nir_frcp(b, norm));
  71.  
  72.          /* Array indices don't have to be normalized, so make a new vector
  73.           * with the coordinate's array index untouched.
  74.           */
  75.          if (tex->coord_components == 4) {
  76.             normalized = nir_vec4(b,
  77.                                   channel(b, normalized, 0),
  78.                                   channel(b, normalized, 1),
  79.                                   channel(b, normalized, 2),
  80.                                   channel(b, orig_coord, 3));
  81.          }
  82.  
  83.          nir_instr_rewrite_src(&tex->instr,
  84.                                &tex->src[i].src,
  85.                                nir_src_for_ssa(normalized));
  86.       }
  87.    }
  88.  
  89.    return true;
  90. }
  91.  
  92. static void
  93. normalize_cubemap_coords_impl(nir_function_impl *impl)
  94. {
  95.    nir_builder b;
  96.    nir_builder_init(&b, impl);
  97.  
  98.    nir_foreach_block(impl, normalize_cubemap_coords_block, &b);
  99.  
  100.    nir_metadata_preserve(impl, nir_metadata_block_index |
  101.                                nir_metadata_dominance);
  102. }
  103.  
  104. void
  105. nir_normalize_cubemap_coords(nir_shader *shader)
  106. {
  107.    nir_foreach_overload(shader, overload)
  108.       if (overload->impl)
  109.          normalize_cubemap_coords_impl(overload->impl);
  110. }
  111.