diff options
Diffstat (limited to 'src/mesa/drivers/dri/r300/compiler/radeon_compiler.c')
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_compiler.c | 489 |
1 files changed, 0 insertions, 489 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c deleted file mode 100644 index b7936725d85..00000000000 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright 2009 Nicolai Hähnle <[email protected]> - * - * 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 - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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. */ - -#include "radeon_compiler.h" - -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> - -#include "radeon_dataflow.h" -#include "radeon_program.h" -#include "radeon_program_pair.h" -#include "radeon_compiler_util.h" - - -void rc_init(struct radeon_compiler * c) -{ - memset(c, 0, sizeof(*c)); - - memory_pool_init(&c->Pool); - c->Program.Instructions.Prev = &c->Program.Instructions; - c->Program.Instructions.Next = &c->Program.Instructions; - c->Program.Instructions.U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE; -} - -void rc_destroy(struct radeon_compiler * c) -{ - rc_constants_destroy(&c->Program.Constants); - memory_pool_destroy(&c->Pool); - free(c->ErrorMsg); -} - -void rc_debug(struct radeon_compiler * c, const char * fmt, ...) -{ - va_list ap; - - if (!(c->Debug & RC_DBG_LOG)) - return; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - -void rc_error(struct radeon_compiler * c, const char * fmt, ...) -{ - va_list ap; - - c->Error = 1; - - if (!c->ErrorMsg) { - /* Only remember the first error */ - char buf[1024]; - int written; - - va_start(ap, fmt); - written = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - if (written < sizeof(buf)) { - c->ErrorMsg = strdup(buf); - } else { - c->ErrorMsg = malloc(written + 1); - - va_start(ap, fmt); - vsnprintf(c->ErrorMsg, written + 1, fmt, ap); - va_end(ap); - } - } - - if (c->Debug & RC_DBG_LOG) { - fprintf(stderr, "r300compiler error: "); - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - } -} - -int rc_if_fail_helper(struct radeon_compiler * c, const char * file, int line, const char * assertion) -{ - rc_error(c, "ICE at %s:%i: assertion failed: %s\n", file, line, assertion); - return 1; -} - -/** - * Recompute c->Program.InputsRead and c->Program.OutputsWritten - * based on which inputs and outputs are actually referenced - * in program instructions. - */ -void rc_calculate_inputs_outputs(struct radeon_compiler * c) -{ - struct rc_instruction *inst; - - c->Program.InputsRead = 0; - c->Program.OutputsWritten = 0; - - for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) - { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - int i; - - for (i = 0; i < opcode->NumSrcRegs; ++i) { - if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT) - c->Program.InputsRead |= 1 << inst->U.I.SrcReg[i].Index; - } - - if (opcode->HasDstReg) { - if (inst->U.I.DstReg.File == RC_FILE_OUTPUT) - c->Program.OutputsWritten |= 1 << inst->U.I.DstReg.Index; - } - } -} - -/** - * Rewrite the program such that everything that source the given input - * register will source new_input instead. - */ -void rc_move_input(struct radeon_compiler * c, unsigned input, struct rc_src_register new_input) -{ - struct rc_instruction * inst; - - c->Program.InputsRead &= ~(1 << input); - - for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - unsigned i; - - for(i = 0; i < opcode->NumSrcRegs; ++i) { - if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT && inst->U.I.SrcReg[i].Index == input) { - inst->U.I.SrcReg[i].File = new_input.File; - inst->U.I.SrcReg[i].Index = new_input.Index; - inst->U.I.SrcReg[i].Swizzle = combine_swizzles(new_input.Swizzle, inst->U.I.SrcReg[i].Swizzle); - if (!inst->U.I.SrcReg[i].Abs) { - inst->U.I.SrcReg[i].Negate ^= new_input.Negate; - inst->U.I.SrcReg[i].Abs = new_input.Abs; - } - - c->Program.InputsRead |= 1 << new_input.Index; - } - } - } -} - - -/** - * Rewrite the program such that everything that writes into the given - * output register will instead write to new_output. The new_output - * writemask is honoured. - */ -void rc_move_output(struct radeon_compiler * c, unsigned output, unsigned new_output, unsigned writemask) -{ - struct rc_instruction * inst; - - c->Program.OutputsWritten &= ~(1 << output); - - for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - - if (opcode->HasDstReg) { - if (inst->U.I.DstReg.File == RC_FILE_OUTPUT && inst->U.I.DstReg.Index == output) { - inst->U.I.DstReg.Index = new_output; - inst->U.I.DstReg.WriteMask &= writemask; - - c->Program.OutputsWritten |= 1 << new_output; - } - } - } -} - - -/** - * Rewrite the program such that a given output is duplicated. - */ -void rc_copy_output(struct radeon_compiler * c, unsigned output, unsigned dup_output) -{ - unsigned tempreg = rc_find_free_temporary(c); - struct rc_instruction * inst; - - for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - - if (opcode->HasDstReg) { - if (inst->U.I.DstReg.File == RC_FILE_OUTPUT && inst->U.I.DstReg.Index == output) { - inst->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst->U.I.DstReg.Index = tempreg; - } - } - } - - inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev); - inst->U.I.Opcode = RC_OPCODE_MOV; - inst->U.I.DstReg.File = RC_FILE_OUTPUT; - inst->U.I.DstReg.Index = output; - - inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; - inst->U.I.SrcReg[0].Index = tempreg; - inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW; - - inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev); - inst->U.I.Opcode = RC_OPCODE_MOV; - inst->U.I.DstReg.File = RC_FILE_OUTPUT; - inst->U.I.DstReg.Index = dup_output; - - inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; - inst->U.I.SrcReg[0].Index = tempreg; - inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW; - - c->Program.OutputsWritten |= 1 << dup_output; -} - - -/** - * Introduce standard code fragment to deal with fragment.position. - */ -void rc_transform_fragment_wpos(struct radeon_compiler * c, unsigned wpos, unsigned new_input, - int full_vtransform) -{ - unsigned tempregi = rc_find_free_temporary(c); - struct rc_instruction * inst_rcp; - struct rc_instruction * inst_mul; - struct rc_instruction * inst_mad; - struct rc_instruction * inst; - - c->Program.InputsRead &= ~(1 << wpos); - c->Program.InputsRead |= 1 << new_input; - - /* perspective divide */ - inst_rcp = rc_insert_new_instruction(c, &c->Program.Instructions); - inst_rcp->U.I.Opcode = RC_OPCODE_RCP; - - inst_rcp->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_rcp->U.I.DstReg.Index = tempregi; - inst_rcp->U.I.DstReg.WriteMask = RC_MASK_W; - - inst_rcp->U.I.SrcReg[0].File = RC_FILE_INPUT; - inst_rcp->U.I.SrcReg[0].Index = new_input; - inst_rcp->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_WWWW; - - inst_mul = rc_insert_new_instruction(c, inst_rcp); - inst_mul->U.I.Opcode = RC_OPCODE_MUL; - - inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_mul->U.I.DstReg.Index = tempregi; - inst_mul->U.I.DstReg.WriteMask = RC_MASK_XYZ; - - inst_mul->U.I.SrcReg[0].File = RC_FILE_INPUT; - inst_mul->U.I.SrcReg[0].Index = new_input; - - inst_mul->U.I.SrcReg[1].File = RC_FILE_TEMPORARY; - inst_mul->U.I.SrcReg[1].Index = tempregi; - inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_WWWW; - - /* viewport transformation */ - inst_mad = rc_insert_new_instruction(c, inst_mul); - inst_mad->U.I.Opcode = RC_OPCODE_MAD; - - inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_mad->U.I.DstReg.Index = tempregi; - inst_mad->U.I.DstReg.WriteMask = RC_MASK_XYZ; - - inst_mad->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; - inst_mad->U.I.SrcReg[0].Index = tempregi; - inst_mad->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0; - - inst_mad->U.I.SrcReg[1].File = RC_FILE_CONSTANT; - inst_mad->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZ0; - - inst_mad->U.I.SrcReg[2].File = RC_FILE_CONSTANT; - inst_mad->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_XYZ0; - - if (full_vtransform) { - inst_mad->U.I.SrcReg[1].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_VIEWPORT_SCALE, 0); - inst_mad->U.I.SrcReg[2].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_VIEWPORT_OFFSET, 0); - } else { - inst_mad->U.I.SrcReg[1].Index = - inst_mad->U.I.SrcReg[2].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_WINDOW_DIMENSION, 0); - } - - for (inst = inst_mad->Next; inst != &c->Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - unsigned i; - - for(i = 0; i < opcode->NumSrcRegs; i++) { - if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT && - inst->U.I.SrcReg[i].Index == wpos) { - inst->U.I.SrcReg[i].File = RC_FILE_TEMPORARY; - inst->U.I.SrcReg[i].Index = tempregi; - } - } - } -} - - -/** - * The FACE input in hardware contains 1 if it's a back face, 0 otherwise. - * Gallium and OpenGL define it the other way around. - * - * So let's just negate FACE at the beginning of the shader and rewrite the rest - * of the shader to read from the newly allocated temporary. - */ -void rc_transform_fragment_face(struct radeon_compiler *c, unsigned face) -{ - unsigned tempregi = rc_find_free_temporary(c); - struct rc_instruction *inst_add; - struct rc_instruction *inst; - - /* perspective divide */ - inst_add = rc_insert_new_instruction(c, &c->Program.Instructions); - inst_add->U.I.Opcode = RC_OPCODE_ADD; - - inst_add->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_add->U.I.DstReg.Index = tempregi; - inst_add->U.I.DstReg.WriteMask = RC_MASK_X; - - inst_add->U.I.SrcReg[0].File = RC_FILE_NONE; - inst_add->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111; - - inst_add->U.I.SrcReg[1].File = RC_FILE_INPUT; - inst_add->U.I.SrcReg[1].Index = face; - inst_add->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XXXX; - inst_add->U.I.SrcReg[1].Negate = RC_MASK_XYZW; - - for (inst = inst_add->Next; inst != &c->Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - unsigned i; - - for(i = 0; i < opcode->NumSrcRegs; i++) { - if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT && - inst->U.I.SrcReg[i].Index == face) { - inst->U.I.SrcReg[i].File = RC_FILE_TEMPORARY; - inst->U.I.SrcReg[i].Index = tempregi; - } - } - } -} - -static void reg_count_callback(void * userdata, struct rc_instruction * inst, - rc_register_file file, unsigned int index, unsigned int mask) -{ - int *max_reg = userdata; - if (file == RC_FILE_TEMPORARY) - (int)index > *max_reg ? *max_reg = index : 0; -} - -void rc_get_stats(struct radeon_compiler *c, struct rc_program_stats *s) -{ - int max_reg = -1; - struct rc_instruction * tmp; - memset(s, 0, sizeof(*s)); - - for(tmp = c->Program.Instructions.Next; tmp != &c->Program.Instructions; - tmp = tmp->Next){ - const struct rc_opcode_info * info; - rc_for_all_reads_mask(tmp, reg_count_callback, &max_reg); - if (tmp->Type == RC_INSTRUCTION_NORMAL) { - info = rc_get_opcode_info(tmp->U.I.Opcode); - if (info->Opcode == RC_OPCODE_BEGIN_TEX) - continue; - if (tmp->U.I.PreSub.Opcode != RC_PRESUB_NONE) - s->num_presub_ops++; - } else { - if (tmp->U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Used) - s->num_presub_ops++; - if (tmp->U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Used) - s->num_presub_ops++; - /* Assuming alpha will never be a flow control or - * a tex instruction. */ - if (tmp->U.P.Alpha.Opcode != RC_OPCODE_NOP) - s->num_alpha_insts++; - if (tmp->U.P.RGB.Opcode != RC_OPCODE_NOP) - s->num_rgb_insts++; - info = rc_get_opcode_info(tmp->U.P.RGB.Opcode); - } - if (info->IsFlowControl) - s->num_fc_insts++; - if (info->HasTexture) - s->num_tex_insts++; - s->num_insts++; - } - s->num_temp_regs = max_reg + 1; -} - -static void print_stats(struct radeon_compiler * c) -{ - struct rc_program_stats s; - - if (c->initial_num_insts <= 5) - return; - - rc_get_stats(c, &s); - - switch (c->type) { - case RC_VERTEX_PROGRAM: - fprintf(stderr,"~~~~~~~~~ VERTEX PROGRAM ~~~~~~~~\n" - "~%4u Instructions\n" - "~%4u Flow Control Instructions\n" - "~%4u Temporary Registers\n" - "~~~~~~~~~~~~~~ END ~~~~~~~~~~~~~~\n", - s.num_insts, s.num_fc_insts, s.num_temp_regs); - break; - - case RC_FRAGMENT_PROGRAM: - fprintf(stderr,"~~~~~~~~ FRAGMENT PROGRAM ~~~~~~~\n" - "~%4u Instructions\n" - "~%4u Vector Instructions (RGB)\n" - "~%4u Scalar Instructions (Alpha)\n" - "~%4u Flow Control Instructions\n" - "~%4u Texture Instructions\n" - "~%4u Presub Operations\n" - "~%4u Temporary Registers\n" - "~~~~~~~~~~~~~~ END ~~~~~~~~~~~~~~\n", - s.num_insts, s.num_rgb_insts, s.num_alpha_insts, - s.num_fc_insts, s.num_tex_insts, s.num_presub_ops, - s.num_temp_regs); - break; - default: - assert(0); - } -} - -static const char *shader_name[RC_NUM_PROGRAM_TYPES] = { - "Vertex Program", - "Fragment Program" -}; - -void rc_run_compiler_passes(struct radeon_compiler *c, struct radeon_compiler_pass *list) -{ - for (unsigned i = 0; list[i].name; i++) { - if (list[i].predicate) { - list[i].run(c, list[i].user); - - if (c->Error) - return; - - if ((c->Debug & RC_DBG_LOG) && list[i].dump) { - fprintf(stderr, "%s: after '%s'\n", shader_name[c->type], list[i].name); - rc_print_program(&c->Program); - } - } - } -} - -/* Executes a list of compiler passes given in the parameter 'list'. */ -void rc_run_compiler(struct radeon_compiler *c, struct radeon_compiler_pass *list) -{ - struct rc_program_stats s; - - rc_get_stats(c, &s); - c->initial_num_insts = s.num_insts; - - if (c->Debug & RC_DBG_LOG) { - fprintf(stderr, "%s: before compilation\n", shader_name[c->type]); - rc_print_program(&c->Program); - } - - rc_run_compiler_passes(c, list); - - if (c->Debug & RC_DBG_STATS) - print_stats(c); -} - -void rc_validate_final_shader(struct radeon_compiler *c, void *user) -{ - /* Check the number of constants. */ - if (c->Program.Constants.Count > c->max_constants) { - rc_error(c, "Too many constants. Max: %i, Got: %i\n", - c->max_constants, c->Program.Constants.Count); - } -} |