diff options
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/i965/Makefile.sources | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_context.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp | 154 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_shader.cpp | 1 |
4 files changed, 157 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources index 82143ac5b54..334bfd92406 100644 --- a/src/mesa/drivers/dri/i965/Makefile.sources +++ b/src/mesa/drivers/dri/i965/Makefile.sources @@ -125,6 +125,7 @@ i965_CXX_FILES = \ brw_fs_reg_allocate.cpp \ brw_fs_schedule_instructions.cpp \ brw_fs_vector_splitting.cpp \ + brw_lower_texture_gradients.cpp \ brw_shader.cpp \ brw_vec4.cpp \ brw_vec4_emit.cpp \ diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index c1f2314f2f2..b4868fe3c26 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -1276,6 +1276,7 @@ brw_program_reloc(struct brw_context *brw, uint32_t state_offset, } bool brw_do_cubemap_normalize(struct exec_list *instructions); +bool brw_lower_texture_gradients(struct exec_list *instructions); #ifdef __cplusplus } diff --git a/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp b/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp new file mode 100644 index 00000000000..dfbb983b726 --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp @@ -0,0 +1,154 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file brw_lower_texture_gradients.cpp + */ + +#include "glsl/ir.h" +#include "glsl/ir_builder.h" + +using namespace ir_builder; + +class lower_texture_grad_visitor : public ir_hierarchical_visitor { +public: + lower_texture_grad_visitor() + { + progress = false; + } + + ir_visitor_status visit_leave(ir_texture *ir); + + + bool progress; + +private: + void emit(ir_variable *, ir_rvalue *); +}; + +/** + * Emit a variable declaration and an assignment to initialize it. + */ +void +lower_texture_grad_visitor::emit(ir_variable *var, ir_rvalue *value) +{ + base_ir->insert_before(var); + base_ir->insert_before(assign(var, value)); +} + +static const glsl_type * +txs_type(const glsl_type *type) +{ + unsigned dims; + switch (type->sampler_dimensionality) { + case GLSL_SAMPLER_DIM_1D: + dims = 1; + break; + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_RECT: + case GLSL_SAMPLER_DIM_CUBE: + dims = 2; + break; + case GLSL_SAMPLER_DIM_3D: + dims = 3; + break; + default: + assert(!"Should not get here: invalid sampler dimensionality"); + } + + if (type->sampler_array) + dims++; + + return glsl_type::get_instance(GLSL_TYPE_INT, dims, 1); +} + +ir_visitor_status +lower_texture_grad_visitor::visit_leave(ir_texture *ir) +{ + /* Only lower textureGrad with shadow samplers */ + if (ir->op != ir_txd || !ir->shadow_comparitor) + return visit_continue; + + /* Cubes are broken. Avoid assertion failures when swizzling. */ + if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) + return visit_continue; + + void *mem_ctx = ralloc_parent(ir); + + const glsl_type *grad_type = ir->lod_info.grad.dPdx->type; + + /* Use textureSize() to get the width and height of LOD 0; swizzle away + * the depth/number of array slices. + */ + ir_texture *txs = new(mem_ctx) ir_texture(ir_txs); + txs->set_sampler(ir->sampler->clone(mem_ctx, NULL), + txs_type(ir->sampler->type)); + txs->lod_info.lod = new(mem_ctx) ir_constant(0); + ir_variable *size = + new(mem_ctx) ir_variable(grad_type, "size", ir_var_temporary); + emit(size, expr(ir_unop_i2f, + swizzle_for_size(txs, grad_type->vector_elements))); + + /* Scale the gradients by width and height. Effectively, the incoming + * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the + * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y). + */ + ir_variable *dPdx = + new(mem_ctx) ir_variable(grad_type, "dPdx", ir_var_temporary); + emit(dPdx, mul(size, ir->lod_info.grad.dPdx)); + + ir_variable *dPdy = + new(mem_ctx) ir_variable(grad_type, "dPdy", ir_var_temporary); + emit(dPdy, mul(size, ir->lod_info.grad.dPdy)); + + /* Calculate rho from equation 3.20 of the GL 3.0 specification. */ + ir_rvalue *rho; + if (dPdx->type->is_scalar()) { + rho = expr(ir_binop_max, expr(ir_unop_abs, dPdx), + expr(ir_unop_abs, dPdy)); + } else { + rho = expr(ir_binop_max, expr(ir_unop_sqrt, dot(dPdx, dPdx)), + expr(ir_unop_sqrt, dot(dPdy, dPdy))); + } + + /* lambda_base = log2(rho). We're ignoring GL state biases for now. */ + ir->op = ir_txl; + ir->lod_info.lod = expr(ir_unop_log2, rho); + + progress = true; + return visit_continue; +} + +extern "C" { + +bool +brw_lower_texture_gradients(struct exec_list *instructions) +{ + lower_texture_grad_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} + +} diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index aa1bfdbd230..140a268cff7 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -157,6 +157,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) lower_if_to_cond_assign(shader->ir, 16); do_lower_texture_projection(shader->ir); + brw_lower_texture_gradients(shader->ir); do_vec_index_to_cond_assign(shader->ir); brw_do_cubemap_normalize(shader->ir); lower_noise(shader->ir); |