diff options
author | Vincent Lejeune <vljn@ovi.com> | 2012-09-17 22:32:30 +0200 |
---|---|---|
committer | Vincent Lejeune <vljn@ovi.com> | 2012-09-18 22:53:38 +0200 |
commit | 8990f18df6f523a0b02d0dec3519309d5178208e (patch) | |
tree | c605c59f3acbfc67881215b2c9eae3392e4a95f4 | |
parent | 168a99f2c7dbe482c89e5ba3a6c5a6961d7a0772 (diff) |
r600g: tgsi-to-llvm generates interpolation intrinsicsinterpolation2
-rw-r--r-- | src/gallium/drivers/r600/r600_llvm.c | 118 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.c | 192 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.h | 38 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/radeon_llvm.h | 9 |
4 files changed, 255 insertions, 102 deletions
diff --git a/src/gallium/drivers/r600/r600_llvm.c b/src/gallium/drivers/r600/r600_llvm.c index e77758b3a7..d78fb63d93 100644 --- a/src/gallium/drivers/r600/r600_llvm.c +++ b/src/gallium/drivers/r600/r600_llvm.c @@ -16,7 +16,7 @@ #include <stdio.h> -#if defined R600_USE_LLVM || defined HAVE_OPENCL +#if 1//defined R600_USE_LLVM || defined HAVE_OPENCL static LLVMValueRef llvm_fetch_const( struct lp_build_tgsi_context * bld_base, @@ -66,7 +66,7 @@ static LLVMValueRef llvm_fetch_system_value( return bitcast(bld_base, type, cval); } -static void llvm_load_input( +static void llvm_load_input_pre_evergreen( struct radeon_llvm_context * ctx, unsigned input_index, const struct tgsi_full_declaration *decl) @@ -89,6 +89,115 @@ static void llvm_load_input( } } +static void llvm_load_input_evergreen( + struct radeon_llvm_context * ctx, + unsigned input_index, + const struct tgsi_full_declaration *decl) +{ + unsigned chan; + const char * intr_name; + + for (chan = 0; chan < 4; chan++) { + unsigned soa_index = radeon_llvm_reg_index_soa(input_index, + chan); + + int reg_index = 0; + + if (ctx->type == TGSI_PROCESSOR_FRAGMENT) { + if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) { + intr_name = "llvm.AMDGPU.load.input.position"; + reg_index = ctx->reserved_reg_count * 4 + chan; + } else if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) { + LLVMValueRef reg = lp_build_const_int32( + ctx->soa.bld_base.base.gallivm, + ctx->tgsi_inputs[input_index].gpr * 4); + LLVMValueRef face = build_intrinsic( + ctx->soa.bld_base.base.gallivm->builder, + "llvm.AMDGPU.load.input.face", + LLVMInt1TypeInContext(ctx->soa.bld_base.base.gallivm->context), + ®, 1, + LLVMReadNoneAttribute); + LLVMValueRef one = lp_build_const_float( + ctx->soa.bld_base.base.gallivm, + 1.0f); + LLVMValueRef minus_one = lp_build_const_float( + ctx->soa.bld_base.base.gallivm, + -1.0f); + ctx->inputs[soa_index] = LLVMBuildSelect( + ctx->soa.bld_base.base.gallivm->builder, + face, + one, minus_one, ""); + continue; + } else { + reg_index = ctx->first_lds ++; + switch (decl->Interp.Interpolate) { + case TGSI_INTERPOLATE_COLOR: + intr_name = "llvm.AMDGPU.load.input.perspective"; + break; + case TGSI_INTERPOLATE_CONSTANT: + intr_name = "llvm.AMDGPU.load.input.constant"; + break; + case TGSI_INTERPOLATE_LINEAR: + intr_name = "llvm.AMDGPU.load.input.linear"; + break; + case TGSI_INTERPOLATE_PERSPECTIVE: + intr_name = "llvm.AMDGPU.load.input.perspective"; + break; + default: + fprintf(stderr, "Warning: Unhandled interpolation mode.\n"); + return; + } + } + } else { + reg_index = ctx->reserved_reg_count * 4 + soa_index; + intr_name = "llvm.R600.load.input"; + } + + + /* The * 4 is assuming that we are in soa mode. */ + LLVMValueRef reg = lp_build_const_int32( + ctx->soa.bld_base.base.gallivm, + reg_index); + + ctx->inputs[soa_index] = build_intrinsic( + ctx->soa.bld_base.base.gallivm->builder, + intr_name, + ctx->soa.bld_base.base.elem_type, ®, 1, + LLVMReadNoneAttribute); + } + + if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR && ctx->two_side) { + for (chan = 0; chan < 4; chan++) { + unsigned soa_index = radeon_llvm_reg_index_soa(input_index, + chan); + LLVMValueRef backcolor_reg = lp_build_const_int32( + ctx->soa.bld_base.base.gallivm, + ctx->last_lds * 4 + chan); + LLVMValueRef backcolor = build_intrinsic( + ctx->soa.bld_base.base.gallivm->builder, + intr_name, + ctx->soa.bld_base.base.elem_type, &backcolor_reg, 1, + LLVMReadNoneAttribute); + LLVMValueRef face_reg = lp_build_const_int32( + ctx->soa.bld_base.base.gallivm, + ctx->face_input * 4); + LLVMValueRef face = build_intrinsic( + ctx->soa.bld_base.base.gallivm->builder, + "llvm.AMDGPU.load.input.face", + LLVMInt1TypeInContext(ctx->soa.bld_base.base.gallivm->context), + &face_reg, 1, + LLVMReadNoneAttribute); + ctx->inputs[soa_index] = LLVMBuildSelect( + ctx->soa.bld_base.base.gallivm->builder, + face, + ctx->inputs[soa_index], + backcolor, + ""); + } + ctx->last_lds++; + } +} + static void llvm_emit_prologue(struct lp_build_tgsi_context * bld_base) { struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base); @@ -225,7 +334,10 @@ LLVMModuleRef r600_tgsi_llvm( bld_base->emit_prologue = llvm_emit_prologue; bld_base->emit_epilogue = llvm_emit_epilogue; ctx->userdata = ctx; - ctx->load_input = llvm_load_input; + if (ctx->chip_class == EVERGREEN || ctx->chip_class == CAYMAN) + ctx->load_input = llvm_load_input_evergreen; + else + ctx->load_input = llvm_load_input_pre_evergreen; ctx->load_system_value = llvm_load_system_value; bld_base->op_actions[TGSI_OPCODE_DP2] = dot_action; diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index 3e797645ed..a860604c02 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -28,8 +28,6 @@ #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_info.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_dump.h" #include "util/u_memory.h" #include <stdio.h> @@ -164,42 +162,6 @@ void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader */ struct r600_shader_tgsi_instruction; -struct r600_shader_src { - unsigned sel; - unsigned swizzle[4]; - unsigned neg; - unsigned abs; - unsigned rel; - uint32_t value[4]; -}; - -struct r600_shader_ctx { - struct tgsi_shader_info info; - struct tgsi_parse_context parse; - const struct tgsi_token *tokens; - unsigned type; - unsigned file_offset[TGSI_FILE_COUNT]; - unsigned temp_reg; - struct r600_shader_tgsi_instruction *inst_info; - struct r600_bytecode *bc; - struct r600_shader *shader; - struct r600_shader_src src[4]; - uint32_t *literals; - uint32_t nliterals; - uint32_t max_driver_temp_used; - /* needed for evergreen interpolation */ - boolean input_centroid; - boolean input_linear; - boolean input_perspective; - int num_interp_gpr; - int face_gpr; - int colors_used; - boolean clip_vertex_write; - unsigned cv_output; - int fragcoord_input; - int native_integers; -}; - struct r600_shader_tgsi_instruction { unsigned tgsi_opcode; unsigned is_op3; @@ -317,6 +279,21 @@ static unsigned r600_alu_from_byte_stream(struct r600_shader_ctx *ctx, alu.bank_swizzle_force = bytes[bytes_read++]; alu.omod = bytes[bytes_read++]; alu.index_mode = bytes[bytes_read++]; + + if (alu.inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INTERP_XY) + { + alu.src[1].sel += 448; + alu.bank_swizzle_force = SQ_ALU_VEC_210; + } + + if( alu.inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INTERP_ZW) { + alu.src[1].sel += 448; + alu.bank_swizzle_force = SQ_ALU_VEC_210; + } + + if (alu.inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INTERP_LOAD_P0) { + alu.src[0].sel += 448; + } if (alu.inst == CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE) || @@ -741,16 +718,18 @@ static int r600_spi_sid(struct r600_shader_io * io) }; /* turn input into interpolate on EG */ -static int evergreen_interp_input(struct r600_shader_ctx *ctx, int index) +static int evergreen_interp_input(struct r600_shader_ctx *ctx, int index, unsigned use_llvm) { int r = 0; if (ctx->shader->input[index].spi_sid) { ctx->shader->input[index].lds_pos = ctx->shader->nlds++; - if (ctx->shader->input[index].interpolate > 0) { - r = evergreen_interp_alu(ctx, index); - } else { - r = evergreen_interp_flat(ctx, index); + if (!use_llvm) { + if (ctx->shader->input[index].interpolate > 0) { + r = evergreen_interp_alu(ctx, index); + } else { + r = evergreen_interp_flat(ctx, index); + } } } return r; @@ -785,7 +764,7 @@ static int select_twoside_color(struct r600_shader_ctx *ctx, int front, int back return 0; } -static int tgsi_declaration(struct r600_shader_ctx *ctx) +static int tgsi_declaration(struct r600_shader_ctx *ctx, unsigned use_llvm) { struct tgsi_full_declaration *d = &ctx->parse.FullToken.FullDeclaration; unsigned i; @@ -813,7 +792,7 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx) break; } if (ctx->bc->chip_class >= EVERGREEN) { - if ((r = evergreen_interp_input(ctx, i))) + if ((r = evergreen_interp_input(ctx, i, use_llvm))) return r; } } @@ -1119,7 +1098,7 @@ static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx) return 0; } -static int process_twoside_color_inputs(struct r600_shader_ctx *ctx) +static int process_twoside_color_inputs(struct r600_shader_ctx *ctx, unsigned use_llvm) { int i, r, count = ctx->shader->ninput; @@ -1146,15 +1125,17 @@ static int process_twoside_color_inputs(struct r600_shader_ctx *ctx) ctx->shader->input[ni].spi_sid = r600_spi_sid(&ctx->shader->input[ni]); ctx->shader->input[ni].gpr = gpr++; - if (ctx->bc->chip_class >= EVERGREEN) { - r = evergreen_interp_input(ctx, ni); + if (!use_llvm) { + if (ctx->bc->chip_class >= EVERGREEN) { + r = evergreen_interp_input(ctx, ni, use_llvm); + if (r) + return r; + } + + r = select_twoside_color(ctx, i, ni); if (r) return r; } - - r = select_twoside_color(ctx, i, ni); - if (r) - return r; } } return 0; @@ -1239,7 +1220,6 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh ctx.file_offset[TGSI_FILE_INPUT] = evergreen_gpr_count(&ctx); } - /* LLVM backend setup */ #ifdef R600_USE_LLVM if (use_llvm && ctx.info.indirect_files) { fprintf(stderr, "Warning: R600 LLVM backend does not support " @@ -1247,34 +1227,13 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh "backend.\n"); use_llvm = 0; } - if (use_llvm) { - struct radeon_llvm_context radeon_llvm_ctx; - LLVMModuleRef mod; - unsigned dump = 0; - memset(&radeon_llvm_ctx, 0, sizeof(radeon_llvm_ctx)); - radeon_llvm_ctx.reserved_reg_count = ctx.file_offset[TGSI_FILE_INPUT]; - mod = r600_tgsi_llvm(&radeon_llvm_ctx, tokens); - if (debug_get_bool_option("R600_DUMP_SHADERS", FALSE)) { - dump = 1; - } - if (r600_llvm_compile(mod, &inst_bytes, &inst_byte_count, - rctx->family, dump)) { - FREE(inst_bytes); - radeon_llvm_dispose(&radeon_llvm_ctx); - use_llvm = 0; - fprintf(stderr, "R600 LLVM backend failed to compile " - "shader. Falling back to TGSI\n"); - } else { - ctx.file_offset[TGSI_FILE_OUTPUT] = - ctx.file_offset[TGSI_FILE_INPUT]; - } - radeon_llvm_dispose(&radeon_llvm_ctx); - } #endif - /* End of LLVM backend setup */ - if (!use_llvm) { + if (use_llvm) { ctx.file_offset[TGSI_FILE_OUTPUT] = + ctx.file_offset[TGSI_FILE_INPUT]; + } else { + ctx.file_offset[TGSI_FILE_OUTPUT] = ctx.file_offset[TGSI_FILE_INPUT] + ctx.info.file_max[TGSI_FILE_INPUT] + 1; } @@ -1310,7 +1269,7 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh ctx.nliterals++; break; case TGSI_TOKEN_TYPE_DECLARATION: - r = tgsi_declaration(&ctx); + r = tgsi_declaration(&ctx, use_llvm); if (r) goto out_err; break; @@ -1336,12 +1295,62 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh } } +/* LLVM backend setup */ +#ifdef R600_USE_LLVM + if (use_llvm) { + struct radeon_llvm_context radeon_llvm_ctx; + LLVMModuleRef mod; + unsigned dump = 0; + memset(&radeon_llvm_ctx, 0, sizeof(radeon_llvm_ctx)); + radeon_llvm_ctx.reserved_reg_count = ctx.file_offset[TGSI_FILE_INPUT]; + radeon_llvm_ctx.type = ctx.type; + radeon_llvm_ctx.two_side = shader->two_side; + radeon_llvm_ctx.face_input = (ctx.face_gpr>=0)?ctx.face_gpr:(ctx.file_offset[TGSI_FILE_INPUT] + + ctx.info.file_max[TGSI_FILE_INPUT] + 1); + radeon_llvm_ctx.tgsi_inputs = ctx.shader->input; + radeon_llvm_ctx.last_lds = ctx.shader->nlds; + radeon_llvm_ctx.chip_class = ctx.bc->chip_class; + mod = r600_tgsi_llvm(&radeon_llvm_ctx, tokens); + if (debug_get_bool_option("R600_DUMP_SHADERS", FALSE)) { + dump = 1; + } + if (r600_llvm_compile(mod, &inst_bytes, &inst_byte_count, + rctx->family, dump)) { + FREE(inst_bytes); + radeon_llvm_dispose(&radeon_llvm_ctx); + use_llvm = 0; + fprintf(stderr, "R600 LLVM backend failed to compile " + "shader. Falling back to TGSI\n"); + } else { + ctx.file_offset[TGSI_FILE_OUTPUT] = + ctx.file_offset[TGSI_FILE_INPUT]; + } + radeon_llvm_dispose(&radeon_llvm_ctx); + } +#endif +/* End of LLVM backend setup */ + if (shader->fs_write_all && rctx->chip_class >= EVERGREEN) shader->nr_ps_max_color_exports = 8; - if (ctx.fragcoord_input >= 0) { - if (ctx.bc->chip_class == CAYMAN) { - for (j = 0 ; j < 4; j++) { + if (!use_llvm) { + if (ctx.fragcoord_input >= 0) { + if (ctx.bc->chip_class == CAYMAN) { + for (j = 0 ; j < 4; j++) { + struct r600_bytecode_alu alu; + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE); + alu.src[0].sel = shader->input[ctx.fragcoord_input].gpr; + alu.src[0].chan = 3; + + alu.dst.sel = shader->input[ctx.fragcoord_input].gpr; + alu.dst.chan = j; + alu.dst.write = (j == 3); + alu.last = 1; + if ((r = r600_bytecode_add_alu(ctx.bc, &alu))) + return r; + } + } else { struct r600_bytecode_alu alu; memset(&alu, 0, sizeof(struct r600_bytecode_alu)); alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE); @@ -1349,30 +1358,17 @@ static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_sh alu.src[0].chan = 3; alu.dst.sel = shader->input[ctx.fragcoord_input].gpr; - alu.dst.chan = j; - alu.dst.write = (j == 3); + alu.dst.chan = 3; + alu.dst.write = 1; alu.last = 1; if ((r = r600_bytecode_add_alu(ctx.bc, &alu))) return r; } - } else { - struct r600_bytecode_alu alu; - memset(&alu, 0, sizeof(struct r600_bytecode_alu)); - alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE); - alu.src[0].sel = shader->input[ctx.fragcoord_input].gpr; - alu.src[0].chan = 3; - - alu.dst.sel = shader->input[ctx.fragcoord_input].gpr; - alu.dst.chan = 3; - alu.dst.write = 1; - alu.last = 1; - if ((r = r600_bytecode_add_alu(ctx.bc, &alu))) - return r; } } if (shader->two_side && ctx.colors_used) { - if ((r = process_twoside_color_inputs(&ctx))) + if ((r = process_twoside_color_inputs(&ctx, use_llvm))) return r; } diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index eb0bbf6ebb..8f70241bcc 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -24,6 +24,44 @@ #define R600_SHADER_H #include "r600_asm.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_scan.h" + +struct r600_shader_src { + unsigned sel; + unsigned swizzle[4]; + unsigned neg; + unsigned abs; + unsigned rel; + uint32_t value[4]; +}; + +struct r600_shader_ctx { + struct tgsi_shader_info info; + struct tgsi_parse_context parse; + const struct tgsi_token *tokens; + unsigned type; + unsigned file_offset[TGSI_FILE_COUNT]; + unsigned temp_reg; + struct r600_shader_tgsi_instruction *inst_info; + struct r600_bytecode *bc; + struct r600_shader *shader; + struct r600_shader_src src[4]; + uint32_t *literals; + uint32_t nliterals; + uint32_t max_driver_temp_used; + /* needed for evergreen interpolation */ + boolean input_centroid; + boolean input_linear; + boolean input_perspective; + int num_interp_gpr; + int face_gpr; + int colors_used; + boolean clip_vertex_write; + unsigned cv_output; + int fragcoord_input; + int native_integers; +}; struct r600_shader_io { unsigned name; diff --git a/src/gallium/drivers/radeon/radeon_llvm.h b/src/gallium/drivers/radeon/radeon_llvm.h index 7a32bb083b..c1d8aaaa61 100644 --- a/src/gallium/drivers/radeon/radeon_llvm.h +++ b/src/gallium/drivers/radeon/radeon_llvm.h @@ -51,8 +51,15 @@ struct radeon_llvm_loop { }; struct radeon_llvm_context { - + unsigned chip_class; struct lp_build_tgsi_soa_context soa; + unsigned type; + unsigned fragcoord_input; + unsigned face_input; + unsigned two_side; + unsigned last_lds; + unsigned first_lds; + struct r600_shader_io * tgsi_inputs; /*=== Front end configuration ===*/ |