From b17f571945d0bb6085bed50f2deaafab274ffac3 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 10 Oct 2014 11:41:20 +0200 Subject: [PATCH] i965/fs: Refactor the texture emission logic into a single function. Before, we had 3 different emit functions for various different gen's, as well as some ancilliary work that was the same across all gen's which was either contained in functions or duplicated across the GLSL IR and Mesa IR backends. Now, we have a single method, emit_texture(), that takes all the information needed to make a texture instruction and handles all the setup, and all we have to do to emit a texture instruction while converting from GLSL IR, Mesa IR, or any new backend is to extract the information emit_texture() needs and then call it. v2: Significant rebasing (by Ken). Signed-off-by: Connor Abbott Signed-off-by: Kenneth Graunke Reviewed-by: Chris Forbes --- src/mesa/drivers/dri/i965/brw_fs.h | 14 ++ src/mesa/drivers/dri/i965/brw_fs_fp.cpp | 28 +-- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 206 +++++++++++-------- 3 files changed, 144 insertions(+), 104 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index dc4e0c8c933..c62c1eb866f 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -488,6 +488,20 @@ public: fs_reg lod, fs_reg lod2, int grad_components, fs_reg sample_index, fs_reg mcs, fs_reg sampler, fs_reg offset_value); + void emit_texture(ir_texture_opcode op, + const glsl_type *dest_type, + fs_reg coordinate, const struct glsl_type *coord_type, + fs_reg shadow_c, + fs_reg lod, fs_reg dpdy, int grad_components, + fs_reg sample_index, + fs_reg offset, unsigned offset_components, + fs_reg mcs, + int gather_component, + bool is_cube_array, + bool is_rect, + uint32_t sampler, + fs_reg sampler_reg, + int texunit); fs_reg emit_mcs_fetch(fs_reg coordinate, int components, fs_reg sampler); void emit_gen6_gather_wa(uint8_t wa, fs_reg dst); fs_reg fix_math_operand(fs_reg src); diff --git a/src/mesa/drivers/dri/i965/brw_fs_fp.cpp b/src/mesa/drivers/dri/i965/brw_fs_fp.cpp index 825d793dc4a..1ba24a9170e 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_fp.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_fp.cpp @@ -476,28 +476,18 @@ fs_visitor::emit_fragment_program_code() unreachable("not reached"); } - int coord_components = coordinate_type->vector_elements; - if (fpi->TexShadow) shadow_c = offset(coordinate, 2); - coordinate = rescale_texcoord(coordinate, coordinate_type, - fpi->TexSrcTarget == TEXTURE_RECT_INDEX, - fpi->TexSrcUnit, fpi->TexSrcUnit); - - fs_inst *inst; - if (brw->gen >= 7) { - inst = emit_texture_gen7(ir->op, dst, coordinate, coord_components, shadow_c, lod, dpdy, 0, sample_index, fs_reg(0u), fs_reg(fpi->TexSrcUnit), texel_offset); - } else if (brw->gen >= 5) { - inst = emit_texture_gen5(ir->op, dst, coordinate, coord_components, shadow_c, lod, dpdy, 0, sample_index, fpi->TexSrcUnit, false); - } else { - inst = emit_texture_gen4(ir->op, dst, coordinate, coord_components, shadow_c, lod, dpdy, 0, fpi->TexSrcUnit); - } - - inst->shadow_compare = fpi->TexShadow; - - /* Reuse the GLSL swizzle_result() handler. */ - swizzle_result(ir->op, 4, dst, fpi->TexSrcUnit); + emit_texture(ir->op, glsl_type::vec4_type, coordinate, coordinate_type, + shadow_c, lod, dpdy, 0, sample_index, + reg_undef, 0, /* offset, components */ + reg_undef, /* mcs */ + 0, /* gather component */ + false, /* is cube array */ + fpi->TexSrcTarget == TEXTURE_RECT_INDEX, + fpi->TexSrcUnit, fs_reg(fpi->TexSrcUnit), + fpi->TexSrcUnit); dst = this->result; break; diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 9008e167df1..8a11b04c0fa 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -1837,7 +1837,19 @@ fs_visitor::emit_mcs_fetch(fs_reg coordinate, int components, fs_reg sampler) } void -fs_visitor::visit(ir_texture *ir) +fs_visitor::emit_texture(ir_texture_opcode op, + const glsl_type *dest_type, + fs_reg coordinate, const struct glsl_type *coord_type, + fs_reg shadow_c, + fs_reg lod, fs_reg lod2, int grad_components, + fs_reg sample_index, + fs_reg offset_value, unsigned offset_components, + fs_reg mcs, + int gather_component, + bool is_cube_array, + bool is_rect, + uint32_t sampler, + fs_reg sampler_reg, int texunit) { const struct brw_sampler_prog_key_data *tex = (stage == MESA_SHADER_FRAGMENT) ? @@ -1845,6 +1857,98 @@ fs_visitor::visit(ir_texture *ir) assert(tex); fs_inst *inst = NULL; + if (op == ir_tg4) { + /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother + * emitting anything other than setting up the constant result. + */ + int swiz = GET_SWZ(tex->swizzles[sampler], gather_component); + if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) { + + fs_reg res = fs_reg(this, glsl_type::vec4_type); + this->result = res; + + for (int i=0; i<4; i++) { + emit(MOV(res, fs_reg(swiz == SWIZZLE_ZERO ? 0.0f : 1.0f))); + res = offset(res, 1); + } + return; + } + } + + if (coordinate.file != BAD_FILE) { + /* FINISHME: Texture coordinate rescaling doesn't work with non-constant + * samplers. This should only be a problem with GL_CLAMP on Gen7. + */ + coordinate = rescale_texcoord(coordinate, coord_type, is_rect, + sampler, texunit); + } + + /* Writemasking doesn't eliminate channels on SIMD8 texture + * samples, so don't worry about them. + */ + fs_reg dst(this, glsl_type::get_instance(dest_type->base_type, 4, 1)); + + int coord_components = coord_type ? coord_type->vector_elements : 0; + + if (brw->gen >= 7) { + inst = emit_texture_gen7(op, dst, coordinate, coord_components, + shadow_c, lod, lod2, grad_components, + sample_index, mcs, sampler_reg, + offset_value); + } else if (brw->gen >= 5) { + inst = emit_texture_gen5(op, dst, coordinate, coord_components, + shadow_c, lod, lod2, grad_components, + sample_index, sampler, + offset_value.file != BAD_FILE); + } else { + inst = emit_texture_gen4(op, dst, coordinate, coord_components, + shadow_c, lod, lod2, grad_components, + sampler); + } + + if (shadow_c.file != BAD_FILE) + inst->shadow_compare = true; + + if (offset_value.file == IMM) + inst->texture_offset = offset_value.fixed_hw_reg.dw1.ud; + + if (op == ir_tg4) { + inst->texture_offset |= + gather_channel(gather_component, sampler) << 16; /* M0.2:16-17 */ + + if (brw->gen == 6) + emit_gen6_gather_wa(tex->gen6_gather_wa[sampler], dst); + } + + /* fixup #layers for cube map arrays */ + if (op == ir_txs && is_cube_array) { + fs_reg depth = offset(dst, 2); + fs_reg fixed_depth = fs_reg(this, glsl_type::int_type); + emit_math(SHADER_OPCODE_INT_QUOTIENT, fixed_depth, depth, fs_reg(6)); + + fs_reg *fixed_payload = ralloc_array(mem_ctx, fs_reg, inst->regs_written); + int components = inst->regs_written / (dst.width / 8); + for (int i = 0; i < components; i++) { + if (i == 2) { + fixed_payload[i] = fixed_depth; + } else { + fixed_payload[i] = offset(dst, i); + } + } + emit(LOAD_PAYLOAD(dst, fixed_payload, components)); + } + + swizzle_result(op, dest_type->vector_elements, dst, sampler); +} + +void +fs_visitor::visit(ir_texture *ir) +{ + const struct brw_sampler_prog_key_data *tex = + (stage == MESA_SHADER_FRAGMENT) ? + &((brw_wm_prog_key*) this->key)->tex : NULL; + assert(tex); + uint32_t sampler = _mesa_get_sampler_uniform_value(ir->sampler, shader_prog, prog); @@ -1889,25 +1993,6 @@ fs_visitor::visit(ir_texture *ir) */ int texunit = prog->SamplerUnits[sampler]; - if (ir->op == ir_tg4) { - /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother - * emitting anything other than setting up the constant result. - */ - ir_constant *chan = ir->lod_info.component->as_constant(); - int swiz = GET_SWZ(tex->swizzles[sampler], chan->value.i[0]); - if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) { - - fs_reg res = fs_reg(this, glsl_type::vec4_type); - this->result = res; - - for (int i=0; i<4; i++) { - emit(MOV(res, fs_reg(swiz == SWIZZLE_ZERO ? 0.0f : 1.0f))); - res = offset(res, 1); - } - return; - } - } - /* Should be lowered by do_lower_texture_projection */ assert(!ir->projector); @@ -1919,19 +2004,13 @@ fs_visitor::visit(ir_texture *ir) * generating these values may involve SEND messages that need the MRFs. */ fs_reg coordinate; + const glsl_type *coord_type = NULL; if (ir->coordinate) { + coord_type = ir->coordinate->type; ir->coordinate->accept(this); - - coordinate = rescale_texcoord(this->result, - ir->coordinate->type, - ir->sampler->type->sampler_dimensionality == - GLSL_SAMPLER_DIM_RECT, - sampler, texunit); + coordinate = this->result; } - int coord_components = - ir->coordinate ? ir->coordinate->type->vector_elements : 0; - fs_reg shadow_comparitor; if (ir->shadow_comparitor) { ir->shadow_comparitor->accept(this); @@ -1939,6 +2018,7 @@ fs_visitor::visit(ir_texture *ir) } fs_reg offset_value; + int offset_components = 0; if (ir->offset) { ir_constant *const_offset = ir->offset->as_constant(); if (const_offset) { @@ -1953,6 +2033,7 @@ fs_visitor::visit(ir_texture *ir) ir->offset->accept(this); offset_value = this->result; } + offset_components = ir->offset->type->vector_elements; } fs_reg lod, lod2, sample_index, mcs; @@ -1996,66 +2077,21 @@ fs_visitor::visit(ir_texture *ir) unreachable("Unrecognized texture opcode"); }; - /* Writemasking doesn't eliminate channels on SIMD8 texture - * samples, so don't worry about them. - */ - fs_reg dst = fs_reg(this, glsl_type::get_instance(ir->type->base_type, 4, 1)); - - if (brw->gen >= 7) { - inst = emit_texture_gen7(ir->op, dst, coordinate, coord_components, - shadow_comparitor, - lod, lod2, grad_components, - sample_index, mcs, sampler_reg, - offset_value); - } else if (brw->gen >= 5) { - inst = emit_texture_gen5(ir->op, dst, coordinate, coord_components, - shadow_comparitor, - lod, lod2, grad_components, - sample_index, sampler, - ir->offset != NULL); - } else { - inst = emit_texture_gen4(ir->op, dst, coordinate, coord_components, - shadow_comparitor, - lod, lod2, grad_components, - sampler); - } - - if (offset_value.file == IMM) - inst->texture_offset = offset_value.fixed_hw_reg.dw1.ud; - + int gather_component = 0; if (ir->op == ir_tg4) - inst->texture_offset |= gather_channel(ir->lod_info.component->as_constant()->value.i[0], sampler) << 16; // M0.2:16-17 + gather_component = ir->lod_info.component->as_constant()->value.i[0]; - if (ir->shadow_comparitor) - inst->shadow_compare = true; - - /* fixup #layers for cube map arrays */ - if (ir->op == ir_txs) { - glsl_type const *type = ir->sampler->type; - if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE && - type->sampler_array) { - fs_reg depth = offset(dst, 2); - fs_reg fixed_depth = fs_reg(this, glsl_type::int_type); - emit_math(SHADER_OPCODE_INT_QUOTIENT, fixed_depth, depth, fs_reg(6)); - - fs_reg *fixed_payload = ralloc_array(mem_ctx, fs_reg, inst->regs_written); - int components = inst->regs_written / (dst.width / 8); - for (int i = 0; i < components; i++) { - if (i == 2) { - fixed_payload[i] = fixed_depth; - } else { - fixed_payload[i] = offset(dst, i); - } - } - emit(LOAD_PAYLOAD(dst, fixed_payload, components)); - } - } + bool is_rect = + ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_RECT; - if (brw->gen == 6 && ir->op == ir_tg4) { - emit_gen6_gather_wa(tex->gen6_gather_wa[sampler], dst); - } + bool is_cube_array = + ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE && + ir->sampler->type->sampler_array; - swizzle_result(ir->op, ir->type->vector_elements, dst, sampler); + emit_texture(ir->op, ir->type, coordinate, coord_type, shadow_comparitor, + lod, lod2, grad_components, sample_index, offset_value, + offset_components, mcs, gather_component, + is_cube_array, is_rect, sampler, sampler_reg, texunit); } /** -- 2.30.2