diff options
author | José Fonseca <jfonseca@vmware.com> | 2009-08-14 10:03:46 +0100 |
---|---|---|
committer | José Fonseca <jfonseca@vmware.com> | 2009-08-29 09:21:32 +0100 |
commit | 95f38dd67c7dfeb3172ef9723c6f8e4c33de0754 (patch) | |
tree | 7ed94f811d1860e3f8f693d582c52d23fae62e90 /src/gallium/drivers/llvmpipe/lp_fs_llvm.c | |
parent | af608e56ca246232ef11a561040b84801ae3a552 (diff) |
llvmpipe: Code generate interpolators.
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_fs_llvm.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_fs_llvm.c | 244 |
1 files changed, 97 insertions, 147 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_fs_llvm.c b/src/gallium/drivers/llvmpipe/lp_fs_llvm.c index 2c1a849785..ef1c8c32c2 100644 --- a/src/gallium/drivers/llvmpipe/lp_fs_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_fs_llvm.c @@ -47,7 +47,10 @@ typedef void -(*lp_shader_fs_func)(void *inputs, +(*lp_shader_fs_func)(void *pos, + void *a0, + void *dadx, + void *dady, void *consts, void *outputs, struct tgsi_sampler **samplers); @@ -65,6 +68,13 @@ struct lp_llvm_fragment_shader LLVMValueRef function; lp_shader_fs_func jit_function; + + union tgsi_exec_channel ALIGN16_ATTRIB pos[NUM_CHANNELS]; + union tgsi_exec_channel ALIGN16_ATTRIB a0[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; + union tgsi_exec_channel ALIGN16_ATTRIB dadx[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; + union tgsi_exec_channel ALIGN16_ATTRIB dady[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; + + uint32_t magic; }; @@ -84,15 +94,19 @@ shader_generate(struct llvmpipe_screen *screen, union lp_type type; LLVMTypeRef elem_type; LLVMTypeRef vec_type; - LLVMTypeRef args[4]; - LLVMValueRef inputs_ptr; + LLVMTypeRef arg_types[7]; + LLVMTypeRef func_type; + LLVMValueRef pos_ptr; + LLVMValueRef a0_ptr; + LLVMValueRef dadx_ptr; + LLVMValueRef dady_ptr; LLVMValueRef consts_ptr; LLVMValueRef outputs_ptr; LLVMValueRef samplers_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; - LLVMValueRef inputs[PIPE_MAX_SHADER_INPUTS][4]; - LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][4]; + LLVMValueRef pos[NUM_CHANNELS]; + LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; char name[32]; unsigned i, j; @@ -106,19 +120,31 @@ shader_generate(struct llvmpipe_screen *screen, elem_type = lp_build_elem_type(type); vec_type = lp_build_vec_type(type); - args[0] = LLVMPointerType(vec_type, 0); - args[1] = LLVMPointerType(elem_type, 0); - args[2] = LLVMPointerType(vec_type, 0); - args[3] = LLVMPointerType(LLVMInt8Type(), 0); - shader->function = LLVMAddFunction(screen->module, "shader", LLVMFunctionType(LLVMVoidType(), args, 4, 0)); - LLVMSetFunctionCallConv(shader->function, LLVMCCallConv); + arg_types[0] = LLVMPointerType(vec_type, 0); /* pos */ + arg_types[1] = LLVMPointerType(vec_type, 0); /* a0 */ + arg_types[2] = LLVMPointerType(vec_type, 0); /* dadx */ + arg_types[3] = LLVMPointerType(vec_type, 0); /* dady */ + arg_types[4] = LLVMPointerType(elem_type, 0); /* consts */ + arg_types[5] = LLVMPointerType(vec_type, 0); /* outputs */ + arg_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */ + + func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); - inputs_ptr = LLVMGetParam(shader->function, 0); - consts_ptr = LLVMGetParam(shader->function, 1); - outputs_ptr = LLVMGetParam(shader->function, 2); - samplers_ptr = LLVMGetParam(shader->function, 3); + shader->function = LLVMAddFunction(screen->module, "shader", func_type); + LLVMSetFunctionCallConv(shader->function, LLVMCCallConv); - LLVMSetValueName(inputs_ptr, "inputs"); + pos_ptr = LLVMGetParam(shader->function, 0); + a0_ptr = LLVMGetParam(shader->function, 1); + dadx_ptr = LLVMGetParam(shader->function, 2); + dady_ptr = LLVMGetParam(shader->function, 3); + consts_ptr = LLVMGetParam(shader->function, 4); + outputs_ptr = LLVMGetParam(shader->function, 5); + samplers_ptr = LLVMGetParam(shader->function, 6); + + LLVMSetValueName(pos_ptr, "pos"); + LLVMSetValueName(a0_ptr, "a0"); + LLVMSetValueName(dadx_ptr, "dadx"); + LLVMSetValueName(dady_ptr, "dady"); LLVMSetValueName(consts_ptr, "consts"); LLVMSetValueName(outputs_ptr, "outputs"); LLVMSetValueName(samplers_ptr, "samplers"); @@ -127,23 +153,23 @@ shader_generate(struct llvmpipe_screen *screen, builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); - for(i = 0; i < PIPE_MAX_SHADER_INPUTS; ++i) { - for(j = 0; j < 4; ++j) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i*4 + j, 0); - util_snprintf(name, sizeof name, "input%u.%c", i, "xywz"[j]); - inputs[i][j] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, inputs_ptr, &index, 1, ""), name); - } + for(j = 0; j < NUM_CHANNELS; ++j) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), j, 0); + util_snprintf(name, sizeof name, "pos.%c", "xyzw"[j]); + pos[j] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, pos_ptr, &index, 1, ""), name); } memset(outputs, 0, sizeof outputs); - lp_build_tgsi_soa(builder, tokens, type, inputs, consts_ptr, outputs, samplers_ptr); + lp_build_tgsi_soa(builder, tokens, type, + pos, a0_ptr, dadx_ptr, dady_ptr, + consts_ptr, outputs, samplers_ptr); for(i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) { - for(j = 0; j < 4; ++j) { + for(j = 0; j < NUM_CHANNELS; ++j) { if(outputs[i][j]) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i*4 + j, 0); - util_snprintf(name, sizeof name, "output%u.%c", i, "xywz"[j]); + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i*NUM_CHANNELS + j, 0); + util_snprintf(name, sizeof name, "output%u.%c", i, "xyzw"[j]); LLVMBuildStore(builder, outputs[i][j], LLVMBuildGEP(builder, outputs_ptr, &index, 1, name)); } } @@ -175,131 +201,56 @@ fs_llvm_prepare( const struct lp_fragment_shader *base, - -/** - * Evaluate a constant-valued coefficient at the position of the - * current quad. - */ static void -eval_constant_coef( - struct tgsi_exec_machine *mach, - unsigned attrib, - unsigned chan ) +setup_pos_vector(struct lp_llvm_fragment_shader *shader, + const struct tgsi_interp_coef *coef, + float x, float y) { - unsigned i; - - for( i = 0; i < QUAD_SIZE; i++ ) { - mach->Inputs[attrib].xyzw[chan].f[i] = mach->InterpCoefs[attrib].a0[chan]; + uint chan; + + /* do X */ + shader->pos[0].f[0] = x; + shader->pos[0].f[1] = x + 1; + shader->pos[0].f[2] = x; + shader->pos[0].f[3] = x + 1; + + /* do Y */ + shader->pos[1].f[0] = y; + shader->pos[1].f[1] = y; + shader->pos[1].f[2] = y + 1; + shader->pos[1].f[3] = y + 1; + + /* do Z and W for all fragments in the quad */ + for (chan = 2; chan < 4; chan++) { + const float dadx = coef->dadx[chan]; + const float dady = coef->dady[chan]; + const float a0 = coef->a0[chan] + dadx * x + dady * y; + shader->pos[chan].f[0] = a0; + shader->pos[chan].f[1] = a0 + dadx; + shader->pos[chan].f[2] = a0 + dady; + shader->pos[chan].f[3] = a0 + dadx + dady; } } -/** - * Evaluate a linear-valued coefficient at the position of the - * current quad. - */ -static void -eval_linear_coef( - struct tgsi_exec_machine *mach, - unsigned attrib, - unsigned chan ) -{ - const float x = mach->QuadPos.xyzw[0].f[0]; - const float y = mach->QuadPos.xyzw[1].f[0]; - const float dadx = mach->InterpCoefs[attrib].dadx[chan]; - const float dady = mach->InterpCoefs[attrib].dady[chan]; - const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y; - mach->Inputs[attrib].xyzw[chan].f[0] = a0; - mach->Inputs[attrib].xyzw[chan].f[1] = a0 + dadx; - mach->Inputs[attrib].xyzw[chan].f[2] = a0 + dady; - mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady; -} - -/** - * Evaluate a perspective-valued coefficient at the position of the - * current quad. - */ -static void -eval_perspective_coef( - struct tgsi_exec_machine *mach, - unsigned attrib, - unsigned chan ) -{ - const float x = mach->QuadPos.xyzw[0].f[0]; - const float y = mach->QuadPos.xyzw[1].f[0]; - const float dadx = mach->InterpCoefs[attrib].dadx[chan]; - const float dady = mach->InterpCoefs[attrib].dady[chan]; - const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y; - const float *w = mach->QuadPos.xyzw[3].f; - /* divide by W here */ - mach->Inputs[attrib].xyzw[chan].f[0] = a0 / w[0]; - mach->Inputs[attrib].xyzw[chan].f[1] = (a0 + dadx) / w[1]; - mach->Inputs[attrib].xyzw[chan].f[2] = (a0 + dady) / w[2]; - mach->Inputs[attrib].xyzw[chan].f[3] = (a0 + dadx + dady) / w[3]; -} - - -typedef void -(*eval_coef_func)(struct tgsi_exec_machine *mach, - unsigned attrib, - unsigned chan ); - static void -exec_declaration( - struct tgsi_exec_machine *mach, - const struct tgsi_full_declaration *decl ) +setup_coef_vector(struct lp_llvm_fragment_shader *shader, + const struct tgsi_interp_coef *coef) { - if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) { - if( decl->Declaration.File == TGSI_FILE_INPUT ) { - unsigned first, last, mask; - eval_coef_func eval; - - first = decl->DeclarationRange.First; - last = decl->DeclarationRange.Last; - mask = decl->Declaration.UsageMask; - - switch( decl->Declaration.Interpolate ) { - case TGSI_INTERPOLATE_CONSTANT: - eval = eval_constant_coef; - break; - - case TGSI_INTERPOLATE_LINEAR: - eval = eval_linear_coef; - break; - - case TGSI_INTERPOLATE_PERSPECTIVE: - eval = eval_perspective_coef; - break; - - default: - eval = NULL; - assert( 0 ); - } - - if( mask == TGSI_WRITEMASK_XYZW ) { - unsigned i, j; - - for( i = first; i <= last; i++ ) { - for( j = 0; j < NUM_CHANNELS; j++ ) { - eval( mach, i, j ); - } - } - } - else { - unsigned i, j; - - for( j = 0; j < NUM_CHANNELS; j++ ) { - if( mask & (1 << j) ) { - for( i = first; i <= last; i++ ) { - eval( mach, i, j ); - } - } - } + unsigned attrib, chan, i; + + for (attrib = 0; attrib < PIPE_MAX_SHADER_INPUTS; ++attrib) { + for (chan = 0; chan < NUM_CHANNELS; ++chan) { + for( i = 0; i < QUAD_SIZE; ++i ) { + shader->a0[attrib][chan].f[i] = coef[attrib].a0[chan]; + shader->dadx[attrib][chan].f[i] = coef[attrib].dadx[chan]; + shader->dady[attrib][chan].f[i] = coef[attrib].dady[chan]; } } } } + /* TODO: codegenerate the whole run function, skip this wrapper. * TODO: break dependency on tgsi_exec_machine struct * TODO: push Position calculation into the generated shader @@ -311,25 +262,24 @@ fs_llvm_run( const struct lp_fragment_shader *base, struct quad_header *quad ) { struct lp_llvm_fragment_shader *shader = lp_llvm_fragment_shader(base); - unsigned i; unsigned mask; /* Compute X, Y, Z, W vals for this quad */ - lp_setup_pos_vector(quad->posCoef, - (float)quad->input.x0, (float)quad->input.y0, - &machine->QuadPos); + setup_pos_vector(shader, + quad->posCoef, + (float)quad->input.x0, (float)quad->input.y0); + + setup_coef_vector(shader, + quad->coef); /* init kill mask */ tgsi_set_kill_mask(machine, 0x0); tgsi_set_exec_mask(machine, 1, 1, 1, 1); - /* execute declarations (interpolants) */ - for (i = 0; i < machine->NumDeclarations; i++) - exec_declaration( machine, &machine->Declarations[i] ); - memset(machine->Outputs, 0, sizeof machine->Outputs); - shader->jit_function( machine->Inputs, + shader->jit_function( shader->pos, + shader->a0, shader->dadx, shader->dady, machine->Consts, machine->Outputs, machine->Samplers); |