Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
  3.  * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
  4.  * Copyright © 2014 Intel Corporation
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the next
  14.  * paragraph) shall be included in all copies or substantial portions of the
  15.  * Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. #include "nir.h"
  27. #include "../program.h"
  28. #include "program/hash_table.h"
  29. #include "ir_uniform.h"
  30.  
  31. extern "C" {
  32. #include "main/compiler.h"
  33. #include "main/mtypes.h"
  34. #include "program/prog_parameter.h"
  35. #include "program/program.h"
  36. }
  37.  
  38. static unsigned
  39. get_sampler_index(const struct gl_shader_program *shader_program,
  40.                   gl_shader_stage stage, const char *name)
  41. {
  42.    unsigned location;
  43.    if (!shader_program->UniformHash->get(location, name)) {
  44.       assert(!"failed to find sampler");
  45.       return 0;
  46.    }
  47.  
  48.    if (!shader_program->UniformStorage[location].sampler[stage].active) {
  49.       assert(!"cannot return a sampler");
  50.       return 0;
  51.    }
  52.  
  53.    return shader_program->UniformStorage[location].sampler[stage].index;
  54. }
  55.  
  56. static void
  57. lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program,
  58.               gl_shader_stage stage, void *mem_ctx)
  59. {
  60.    if (instr->sampler == NULL)
  61.       return;
  62.  
  63.    /* Get the name and the offset */
  64.    instr->sampler_index = 0;
  65.    char *name = ralloc_strdup(mem_ctx, instr->sampler->var->name);
  66.  
  67.    for (nir_deref *deref = &instr->sampler->deref;
  68.         deref->child; deref = deref->child) {
  69.       switch (deref->child->deref_type) {
  70.       case nir_deref_type_array: {
  71.          nir_deref_array *deref_array = nir_deref_as_array(deref->child);
  72.  
  73.          assert(deref_array->deref_array_type != nir_deref_array_type_wildcard);
  74.  
  75.          if (deref_array->deref.child) {
  76.             ralloc_asprintf_append(&name, "[%u]",
  77.                deref_array->deref_array_type == nir_deref_array_type_direct ?
  78.                   deref_array->base_offset : 0);
  79.          } else {
  80.             assert(deref->child->type->base_type == GLSL_TYPE_SAMPLER);
  81.             instr->sampler_index = deref_array->base_offset;
  82.          }
  83.  
  84.          /* XXX: We're assuming here that the indirect is the last array
  85.           * thing we have.  This should be ok for now as we don't support
  86.           * arrays_of_arrays yet.
  87.           */
  88.          if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
  89.             /* First, we have to resize the array of texture sources */
  90.             nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
  91.                                                   instr->num_srcs + 1);
  92.  
  93.             for (unsigned i = 0; i < instr->num_srcs; i++) {
  94.                new_srcs[i].src_type = instr->src[i].src_type;
  95.                nir_instr_move_src(&instr->instr, &new_srcs[i].src,
  96.                                   &instr->src[i].src);
  97.             }
  98.  
  99.             ralloc_free(instr->src);
  100.             instr->src = new_srcs;
  101.  
  102.             /* Now we can go ahead and move the source over to being a
  103.              * first-class texture source.
  104.              */
  105.             instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
  106.             instr->num_srcs++;
  107.             nir_instr_move_src(&instr->instr,
  108.                                &instr->src[instr->num_srcs - 1].src,
  109.                                &deref_array->indirect);
  110.  
  111.             instr->sampler_array_size = glsl_get_length(deref->type);
  112.          }
  113.          break;
  114.       }
  115.  
  116.       case nir_deref_type_struct: {
  117.          nir_deref_struct *deref_struct = nir_deref_as_struct(deref->child);
  118.          const char *field = glsl_get_struct_elem_name(deref->type,
  119.                                                        deref_struct->index);
  120.          ralloc_asprintf_append(&name, ".%s", field);
  121.          break;
  122.       }
  123.  
  124.       default:
  125.          unreachable("Invalid deref type");
  126.          break;
  127.       }
  128.    }
  129.  
  130.    instr->sampler_index += get_sampler_index(shader_program, stage, name);
  131.  
  132.    instr->sampler = NULL;
  133. }
  134.  
  135. typedef struct {
  136.    void *mem_ctx;
  137.    const struct gl_shader_program *shader_program;
  138.    gl_shader_stage stage;
  139. } lower_state;
  140.  
  141. static bool
  142. lower_block_cb(nir_block *block, void *_state)
  143. {
  144.    lower_state *state = (lower_state *) _state;
  145.  
  146.    nir_foreach_instr(block, instr) {
  147.       if (instr->type == nir_instr_type_tex) {
  148.          nir_tex_instr *tex_instr = nir_instr_as_tex(instr);
  149.          lower_sampler(tex_instr, state->shader_program, state->stage,
  150.                        state->mem_ctx);
  151.       }
  152.    }
  153.  
  154.    return true;
  155. }
  156.  
  157. static void
  158. lower_impl(nir_function_impl *impl, const struct gl_shader_program *shader_program,
  159.            gl_shader_stage stage)
  160. {
  161.    lower_state state;
  162.  
  163.    state.mem_ctx = ralloc_parent(impl);
  164.    state.shader_program = shader_program;
  165.    state.stage = stage;
  166.  
  167.    nir_foreach_block(impl, lower_block_cb, &state);
  168. }
  169.  
  170. extern "C" void
  171. nir_lower_samplers(nir_shader *shader, const struct gl_shader_program *shader_program,
  172.                    gl_shader_stage stage)
  173. {
  174.    nir_foreach_overload(shader, overload) {
  175.       if (overload->impl)
  176.          lower_impl(overload->impl, shader_program, stage);
  177.    }
  178. }
  179.