Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2012 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
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. /**
  25.  * \file brw_lower_texture_gradients.cpp
  26.  */
  27.  
  28. #include "glsl/ir.h"
  29. #include "glsl/ir_builder.h"
  30. #include "program/prog_instruction.h"
  31. #include "brw_context.h"
  32.  
  33. using namespace ir_builder;
  34.  
  35. class lower_texture_grad_visitor : public ir_hierarchical_visitor {
  36. public:
  37.    lower_texture_grad_visitor(bool has_sample_d_c)
  38.       : has_sample_d_c(has_sample_d_c)
  39.    {
  40.       progress = false;
  41.    }
  42.  
  43.    ir_visitor_status visit_leave(ir_texture *ir);
  44.  
  45.  
  46.    bool progress;
  47.    bool has_sample_d_c;
  48.  
  49. private:
  50.    void emit(ir_variable *, ir_rvalue *);
  51. };
  52.  
  53. /**
  54.  * Emit a variable declaration and an assignment to initialize it.
  55.  */
  56. void
  57. lower_texture_grad_visitor::emit(ir_variable *var, ir_rvalue *value)
  58. {
  59.    base_ir->insert_before(var);
  60.    base_ir->insert_before(assign(var, value));
  61. }
  62.  
  63. static const glsl_type *
  64. txs_type(const glsl_type *type)
  65. {
  66.    unsigned dims;
  67.    switch (type->sampler_dimensionality) {
  68.    case GLSL_SAMPLER_DIM_1D:
  69.       dims = 1;
  70.       break;
  71.    case GLSL_SAMPLER_DIM_2D:
  72.    case GLSL_SAMPLER_DIM_RECT:
  73.    case GLSL_SAMPLER_DIM_CUBE:
  74.       dims = 2;
  75.       break;
  76.    case GLSL_SAMPLER_DIM_3D:
  77.       dims = 3;
  78.       break;
  79.    default:
  80.       assert(!"Should not get here: invalid sampler dimensionality");
  81.       dims = 2;
  82.    }
  83.  
  84.    if (type->sampler_array)
  85.       dims++;
  86.  
  87.    return glsl_type::get_instance(GLSL_TYPE_INT, dims, 1);
  88. }
  89.  
  90. ir_visitor_status
  91. lower_texture_grad_visitor::visit_leave(ir_texture *ir)
  92. {
  93.    /* Only lower textureGrad with shadow samplers */
  94.    if (ir->op != ir_txd || !ir->shadow_comparitor)
  95.       return visit_continue;
  96.  
  97.    /* Lower textureGrad() with samplerCubeShadow even if we have the sample_d_c
  98.     * message.  GLSL provides gradients for the 'r' coordinate.  Unfortunately:
  99.     *
  100.     * From the Ivybridge PRM, Volume 4, Part 1, sample_d message description:
  101.     * "The r coordinate contains the faceid, and the r gradients are ignored
  102.     *  by hardware."
  103.     *
  104.     * We likely need to do a similar treatment for samplerCube and
  105.     * samplerCubeArray, but we have insufficient testing for that at the moment.
  106.     */
  107.    bool need_lowering = !has_sample_d_c ||
  108.       ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE;
  109.  
  110.    if (!need_lowering)
  111.       return visit_continue;
  112.  
  113.    void *mem_ctx = ralloc_parent(ir);
  114.  
  115.    const glsl_type *grad_type = ir->lod_info.grad.dPdx->type;
  116.  
  117.    /* Use textureSize() to get the width and height of LOD 0; swizzle away
  118.     * the depth/number of array slices.
  119.     */
  120.    ir_texture *txs = new(mem_ctx) ir_texture(ir_txs);
  121.    txs->set_sampler(ir->sampler->clone(mem_ctx, NULL),
  122.                     txs_type(ir->sampler->type));
  123.    txs->lod_info.lod = new(mem_ctx) ir_constant(0);
  124.    ir_variable *size =
  125.       new(mem_ctx) ir_variable(grad_type, "size", ir_var_temporary);
  126.    if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
  127.       base_ir->insert_before(size);
  128.       base_ir->insert_before(assign(size, expr(ir_unop_i2f, txs), WRITEMASK_XY));
  129.       base_ir->insert_before(assign(size, new(mem_ctx) ir_constant(1.0f), WRITEMASK_Z));
  130.    } else {
  131.       emit(size, expr(ir_unop_i2f,
  132.                       swizzle_for_size(txs, grad_type->vector_elements)));
  133.    }
  134.  
  135.    /* Scale the gradients by width and height.  Effectively, the incoming
  136.     * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the
  137.     * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y).
  138.     */
  139.    ir_variable *dPdx =
  140.       new(mem_ctx) ir_variable(grad_type, "dPdx", ir_var_temporary);
  141.    emit(dPdx, mul(size, ir->lod_info.grad.dPdx));
  142.  
  143.    ir_variable *dPdy =
  144.       new(mem_ctx) ir_variable(grad_type, "dPdy", ir_var_temporary);
  145.    emit(dPdy, mul(size, ir->lod_info.grad.dPdy));
  146.  
  147.    /* Calculate rho from equation 3.20 of the GL 3.0 specification. */
  148.    ir_rvalue *rho;
  149.    if (dPdx->type->is_scalar()) {
  150.       rho = expr(ir_binop_max, expr(ir_unop_abs, dPdx),
  151.                                expr(ir_unop_abs, dPdy));
  152.    } else {
  153.       rho = expr(ir_binop_max, expr(ir_unop_sqrt, dot(dPdx, dPdx)),
  154.                                expr(ir_unop_sqrt, dot(dPdy, dPdy)));
  155.    }
  156.  
  157.    /* lambda_base = log2(rho).  We're ignoring GL state biases for now. */
  158.    ir->op = ir_txl;
  159.    ir->lod_info.lod = expr(ir_unop_log2, rho);
  160.  
  161.    progress = true;
  162.    return visit_continue;
  163. }
  164.  
  165. extern "C" {
  166.  
  167. bool
  168. brw_lower_texture_gradients(struct brw_context *brw,
  169.                             struct exec_list *instructions)
  170. {
  171.    bool has_sample_d_c = brw->gen >= 8 || brw->is_haswell;
  172.    lower_texture_grad_visitor v(has_sample_d_c);
  173.  
  174.    visit_list_elements(&v, instructions);
  175.  
  176.    return v.progress;
  177. }
  178.  
  179. }
  180.