Subversion Repositories Kolibri OS

Rev

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.       unreachable("Should not get here: invalid sampler dimensionality");
  81.    }
  82.  
  83.    if (type->sampler_array)
  84.       dims++;
  85.  
  86.    return glsl_type::get_instance(GLSL_TYPE_INT, dims, 1);
  87. }
  88.  
  89. ir_visitor_status
  90. lower_texture_grad_visitor::visit_leave(ir_texture *ir)
  91. {
  92.    /* Only lower textureGrad with shadow samplers */
  93.    if (ir->op != ir_txd || !ir->shadow_comparitor)
  94.       return visit_continue;
  95.  
  96.    /* Lower textureGrad() with samplerCubeShadow even if we have the sample_d_c
  97.     * message.  GLSL provides gradients for the 'r' coordinate.  Unfortunately:
  98.     *
  99.     * From the Ivybridge PRM, Volume 4, Part 1, sample_d message description:
  100.     * "The r coordinate contains the faceid, and the r gradients are ignored
  101.     *  by hardware."
  102.     *
  103.     * We likely need to do a similar treatment for samplerCube and
  104.     * samplerCubeArray, but we have insufficient testing for that at the moment.
  105.     */
  106.    bool need_lowering = !has_sample_d_c ||
  107.       ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE;
  108.  
  109.    if (!need_lowering)
  110.       return visit_continue;
  111.  
  112.    void *mem_ctx = ralloc_parent(ir);
  113.  
  114.    const glsl_type *grad_type = ir->lod_info.grad.dPdx->type;
  115.  
  116.    /* Use textureSize() to get the width and height of LOD 0; swizzle away
  117.     * the depth/number of array slices.
  118.     */
  119.    ir_texture *txs = new(mem_ctx) ir_texture(ir_txs);
  120.    txs->set_sampler(ir->sampler->clone(mem_ctx, NULL),
  121.                     txs_type(ir->sampler->type));
  122.    txs->lod_info.lod = new(mem_ctx) ir_constant(0);
  123.    ir_variable *size =
  124.       new(mem_ctx) ir_variable(grad_type, "size", ir_var_temporary);
  125.    if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
  126.       base_ir->insert_before(size);
  127.       base_ir->insert_before(assign(size,
  128.                                     swizzle_for_size(expr(ir_unop_i2f, txs), 2),
  129.                                     WRITEMASK_XY));
  130.       base_ir->insert_before(assign(size, new(mem_ctx) ir_constant(1.0f), WRITEMASK_Z));
  131.    } else {
  132.       emit(size, expr(ir_unop_i2f,
  133.                       swizzle_for_size(txs, grad_type->vector_elements)));
  134.    }
  135.  
  136.    /* Scale the gradients by width and height.  Effectively, the incoming
  137.     * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the
  138.     * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y).
  139.     */
  140.    ir_variable *dPdx =
  141.       new(mem_ctx) ir_variable(grad_type, "dPdx", ir_var_temporary);
  142.    emit(dPdx, mul(size, ir->lod_info.grad.dPdx));
  143.  
  144.    ir_variable *dPdy =
  145.       new(mem_ctx) ir_variable(grad_type, "dPdy", ir_var_temporary);
  146.    emit(dPdy, mul(size, ir->lod_info.grad.dPdy));
  147.  
  148.    /* Calculate rho from equation 3.20 of the GL 3.0 specification. */
  149.    ir_rvalue *rho;
  150.    if (dPdx->type->is_scalar()) {
  151.       rho = expr(ir_binop_max, expr(ir_unop_abs, dPdx),
  152.                                expr(ir_unop_abs, dPdy));
  153.    } else {
  154.       rho = expr(ir_binop_max, expr(ir_unop_sqrt, dot(dPdx, dPdx)),
  155.                                expr(ir_unop_sqrt, dot(dPdy, dPdy)));
  156.    }
  157.  
  158.    /* lambda_base = log2(rho).  We're ignoring GL state biases for now. */
  159.    ir->op = ir_txl;
  160.    ir->lod_info.lod = expr(ir_unop_log2, rho);
  161.  
  162.    progress = true;
  163.    return visit_continue;
  164. }
  165.  
  166. extern "C" {
  167.  
  168. bool
  169. brw_lower_texture_gradients(struct brw_context *brw,
  170.                             struct exec_list *instructions)
  171. {
  172.    bool has_sample_d_c = brw->gen >= 8 || brw->is_haswell;
  173.    lower_texture_grad_visitor v(has_sample_d_c);
  174.  
  175.    visit_list_elements(&v, instructions);
  176.  
  177.    return v.progress;
  178. }
  179.  
  180. }
  181.