diff options
author | Dave Airlie <[email protected]> | 2017-11-15 10:03:32 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2017-11-17 11:31:41 +1000 |
commit | 31db4a3200b3ff2fe9521c62c16ea363d9faea2e (patch) | |
tree | 1a6c436f157fab17cba3e9636f45797b11c40eca /src/gallium | |
parent | f94f5c9a9f7a41f688659450d52e19e8295fce4a (diff) |
r600: handle image size support.
This adds support for the RESQ opcode with the workaround
required due to hw bugs for buffers and cube arrays.
Tested-By: Gert Wollny <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.c | 78 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 30 |
3 files changed, 101 insertions, 9 deletions
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index b83ca119822..9d0e6252957 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -3077,6 +3077,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx, shader->two_side = key.ps.color_two_side; shader->atomic_base = key.ps.first_atomic_counter; shader->rat_base = key.ps.nr_cbufs; + shader->image_size_const_offset = key.ps.image_size_const_offset; break; default: break; @@ -6805,12 +6806,12 @@ static int do_vtx_fetch_inst(struct r600_shader_ctx *ctx, boolean src_requires_l return 0; } -static int r600_do_buffer_txq(struct r600_shader_ctx *ctx) +static int r600_do_buffer_txq(struct r600_shader_ctx *ctx, int reg_idx, int offset) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bytecode_alu alu; int r; - int id = tgsi_tex_get_src_gpr(ctx, 1); + int id = tgsi_tex_get_src_gpr(ctx, reg_idx) + offset; memset(&alu, 0, sizeof(struct r600_bytecode_alu)); alu.op = ALU_OP1_MOV; @@ -6887,7 +6888,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) if (inst->Texture.Texture == TGSI_TEXTURE_BUFFER) { if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ) { ctx->shader->uses_tex_buffers = true; - return r600_do_buffer_txq(ctx); + return r600_do_buffer_txq(ctx, 1, 0); } else if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) { if (ctx->bc->chip_class < EVERGREEN) @@ -8198,6 +8199,73 @@ static int tgsi_atomic_op(struct r600_shader_ctx *ctx) return 0; } +static int tgsi_resq(struct r600_shader_ctx *ctx) +{ + struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; + unsigned sampler_index_mode; + struct r600_bytecode_tex tex; + int r; + boolean has_txq_cube_array_z = false; + + if (inst->Memory.Texture == TGSI_TEXTURE_BUFFER) { + ctx->shader->uses_tex_buffers = true; + return r600_do_buffer_txq(ctx, 0, ctx->shader->image_size_const_offset); + } + + if (inst->Memory.Texture == TGSI_TEXTURE_CUBE_ARRAY && + inst->Dst[0].Register.WriteMask & 4) { + ctx->shader->has_txq_cube_array_z_comp = true; + has_txq_cube_array_z = true; + } + + sampler_index_mode = inst->Src[0].Indirect.Index == 2 ? 2 : 0; // CF_INDEX_1 : CF_INDEX_NONE + if (sampler_index_mode) + egcm_load_index_reg(ctx->bc, 1, false); + + + /* does this shader want a num layers from TXQ for a cube array? */ + if (has_txq_cube_array_z) { + int id = tgsi_tex_get_src_gpr(ctx, 0) + ctx->shader->image_size_const_offset; + struct r600_bytecode_alu alu; + + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.op = ALU_OP1_MOV; + + alu.src[0].sel = R600_SHADER_BUFFER_INFO_SEL; + /* channel 1 or 3 of each word */ + alu.src[0].sel += (id / 2); + alu.src[0].chan = ((id % 2) * 2) + 1; + alu.src[0].kc_bank = R600_BUFFER_INFO_CONST_BUFFER; + tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst); + alu.last = 1; + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + /* disable writemask from texture instruction */ + inst->Dst[0].Register.WriteMask &= ~4; + } + memset(&tex, 0, sizeof(struct r600_bytecode_tex)); + tex.op = ctx->inst_info->op; + tex.sampler_id = R600_IMAGE_REAL_RESOURCE_OFFSET + inst->Src[0].Register.Index; + tex.sampler_index_mode = sampler_index_mode; + tex.resource_id = tex.sampler_id; + tex.resource_index_mode = sampler_index_mode; + tex.src_sel_x = 4; + tex.src_sel_y = 4; + tex.src_sel_z = 4; + tex.src_sel_w = 4; + tex.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 0 : 7; + tex.dst_sel_y = (inst->Dst[0].Register.WriteMask & 2) ? 1 : 7; + tex.dst_sel_z = (inst->Dst[0].Register.WriteMask & 4) ? 2 : 7; + tex.dst_sel_w = (inst->Dst[0].Register.WriteMask & 8) ? 3 : 7; + tex.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index; + r = r600_bytecode_add_tex(ctx->bc, &tex); + if (r) + return r; + + return 0; +} + static int tgsi_lrp(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; @@ -9845,7 +9913,7 @@ static const struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] = [TGSI_OPCODE_ENDSUB] = { ALU_OP0_NOP, tgsi_unsupported}, [103] = { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_tex}, [TGSI_OPCODE_TXQS] = { FETCH_OP_GET_NUMBER_OF_SAMPLES, tgsi_tex}, - [TGSI_OPCODE_RESQ] = { ALU_OP0_NOP, tgsi_unsupported}, + [TGSI_OPCODE_RESQ] = { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_resq}, [106] = { ALU_OP0_NOP, tgsi_unsupported}, [TGSI_OPCODE_NOP] = { ALU_OP0_NOP, tgsi_unsupported}, [TGSI_OPCODE_FSEQ] = { ALU_OP2_SETE_DX10, tgsi_op2}, @@ -10068,7 +10136,7 @@ static const struct r600_shader_tgsi_instruction cm_shader_tgsi_instruction[] = [TGSI_OPCODE_ENDSUB] = { ALU_OP0_NOP, tgsi_unsupported}, [103] = { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_tex}, [TGSI_OPCODE_TXQS] = { FETCH_OP_GET_NUMBER_OF_SAMPLES, tgsi_tex}, - [TGSI_OPCODE_RESQ] = { ALU_OP0_NOP, tgsi_unsupported}, + [TGSI_OPCODE_RESQ] = { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_resq}, [106] = { ALU_OP0_NOP, tgsi_unsupported}, [TGSI_OPCODE_NOP] = { ALU_OP0_NOP, tgsi_unsupported}, [TGSI_OPCODE_FSEQ] = { ALU_OP2_SETE_DX10, tgsi_op2}, diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index ccbcd6723ad..5d6501c8d38 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -119,12 +119,14 @@ struct r600_shader { boolean uses_images; uint8_t atomic_base; uint8_t rat_base; + uint8_t image_size_const_offset; }; union r600_shader_key { struct { unsigned nr_cbufs:4; unsigned first_atomic_counter:4; + unsigned image_size_const_offset:5; unsigned color_two_side:1; unsigned alpha_to_one:1; } ps; diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 1bd0a7647b8..b8d4b8f70fa 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -799,6 +799,8 @@ static inline void r600_shader_selector_key(const struct pipe_context *ctx, key->gs.tri_strip_adj_fix = rctx->gs_tri_strip_adj_fix; break; case PIPE_SHADER_FRAGMENT: { + if (rctx->ps_shader->info.images_declared) + key->ps.image_size_const_offset = util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].views.enabled_mask); key->ps.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_FRAGMENT); key->ps.color_two_side = rctx->rasterizer && rctx->rasterizer->two_side; key->ps.alpha_to_one = rctx->alpha_to_one && @@ -1330,29 +1332,49 @@ static void r600_setup_buffer_constants(struct r600_context *rctx, int shader_ty static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type) { struct r600_textures_info *samplers = &rctx->samplers[shader_type]; - int bits; + struct r600_image_state *images = NULL; + int bits, sview_bits; uint32_t array_size; int i; uint32_t *constants; uint32_t base_offset; - if (!samplers->views.dirty_buffer_constants) + + if (shader_type == PIPE_SHADER_FRAGMENT) + images = &rctx->fragment_images; + + if (!samplers->views.dirty_buffer_constants && + (images && !images->dirty_buffer_constants)) return; + if (images) + images->dirty_buffer_constants = FALSE; samplers->views.dirty_buffer_constants = FALSE; - bits = util_last_bit(samplers->views.enabled_mask); + bits = sview_bits = util_last_bit(samplers->views.enabled_mask); + if (images) + bits += util_last_bit(images->enabled_mask); array_size = bits * 2 * sizeof(uint32_t) * 4; constants = r600_alloc_buf_consts(rctx, shader_type, array_size, &base_offset); - for (i = 0; i < bits; i++) { + for (i = 0; i < sview_bits; i++) { if (samplers->views.enabled_mask & (1 << i)) { uint32_t offset = (base_offset / 4) + i * 2; constants[offset] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format); constants[offset + 1] = samplers->views.views[i]->base.texture->array_size / 6; } } + if (images) { + for (i = sview_bits; i < bits; i++) { + int idx = i - sview_bits; + if (images->enabled_mask & (1 << idx)) { + uint32_t offset = (base_offset / 4) + i * 2; + constants[offset] = images->views[i].base.resource->width0 / util_format_get_blocksize(images->views[i].base.format); + constants[offset + 1] = images->views[i].base.resource->array_size / 6; + } + } + } } /* set sample xy locations as array of fragment shader constants */ |