2 * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23 #include "radeon_compiler.h"
27 #include "radeon_dataflow.h"
28 #include "radeon_emulate_branches.h"
29 #include "radeon_emulate_loops.h"
30 #include "radeon_program_alu.h"
31 #include "radeon_program_tex.h"
32 #include "radeon_rename_regs.h"
33 #include "radeon_remove_constants.h"
34 #include "r300_fragprog.h"
35 #include "r300_fragprog_swizzle.h"
36 #include "r500_fragprog.h"
39 static void dataflow_outputs_mark_use(void * userdata
, void * data
,
40 void (*callback
)(void *, unsigned int, unsigned int))
42 struct r300_fragment_program_compiler
* c
= userdata
;
43 callback(data
, c
->OutputColor
[0], RC_MASK_XYZW
);
44 callback(data
, c
->OutputColor
[1], RC_MASK_XYZW
);
45 callback(data
, c
->OutputColor
[2], RC_MASK_XYZW
);
46 callback(data
, c
->OutputColor
[3], RC_MASK_XYZW
);
47 callback(data
, c
->OutputDepth
, RC_MASK_W
);
50 static void rc_rewrite_depth_out(struct radeon_compiler
*cc
, void *user
)
52 struct r300_fragment_program_compiler
*c
= (struct r300_fragment_program_compiler
*)cc
;
53 struct rc_instruction
*rci
;
55 for (rci
= c
->Base
.Program
.Instructions
.Next
; rci
!= &c
->Base
.Program
.Instructions
; rci
= rci
->Next
) {
56 struct rc_sub_instruction
* inst
= &rci
->U
.I
;
58 if (inst
->DstReg
.File
!= RC_FILE_OUTPUT
|| inst
->DstReg
.Index
!= c
->OutputDepth
)
61 if (inst
->DstReg
.WriteMask
& RC_MASK_Z
) {
62 inst
->DstReg
.WriteMask
= RC_MASK_W
;
64 inst
->DstReg
.WriteMask
= 0;
68 switch (inst
->Opcode
) {
71 inst
->SrcReg
[0] = lmul_swizzle(RC_SWIZZLE_ZZZZ
, inst
->SrcReg
[0]);
77 inst
->SrcReg
[0] = lmul_swizzle(RC_SWIZZLE_ZZZZ
, inst
->SrcReg
[0]);
78 inst
->SrcReg
[1] = lmul_swizzle(RC_SWIZZLE_ZZZZ
, inst
->SrcReg
[1]);
82 inst
->SrcReg
[0] = lmul_swizzle(RC_SWIZZLE_ZZZZ
, inst
->SrcReg
[0]);
83 inst
->SrcReg
[1] = lmul_swizzle(RC_SWIZZLE_ZZZZ
, inst
->SrcReg
[1]);
84 inst
->SrcReg
[2] = lmul_swizzle(RC_SWIZZLE_ZZZZ
, inst
->SrcReg
[2]);
87 // Scalar instructions needn't be reswizzled
93 void r3xx_compile_fragment_program(struct r300_fragment_program_compiler
* c
)
95 int is_r500
= c
->Base
.is_r500
;
96 int kill_consts
= c
->Base
.remove_unused_constants
;
97 int opt
= !c
->Base
.disable_optimizations
;
99 /* Lists of instruction transformations. */
100 struct radeon_program_transformation rewrite_tex
[] = {
101 { &radeonTransformTEX
, c
},
105 struct radeon_program_transformation native_rewrite_r500
[] = {
106 { &r500_transform_IF
, 0 },
107 { &radeonTransformALU
, 0 },
108 { &radeonTransformDeriv
, 0 },
109 { &radeonTransformTrigScale
, 0 },
113 struct radeon_program_transformation native_rewrite_r300
[] = {
114 { &radeonTransformALU
, 0 },
115 { &r300_transform_trig_simple
, 0 },
119 /* List of compiler passes. */
120 struct radeon_compiler_pass fs_list
[] = {
121 /* NAME DUMP PREDICATE FUNCTION PARAM */
122 {"rewrite depth out", 1, 1, rc_rewrite_depth_out
, NULL
},
123 /* This transformation needs to be done before any of the IF
124 * instructions are modified. */
125 {"transform KILP", 1, 1, rc_transform_KILP
, NULL
},
126 {"unroll loops", 1, is_r500
, rc_unroll_loops
, NULL
},
127 {"transform loops", 1, !is_r500
, rc_transform_loops
, NULL
},
128 {"emulate branches", 1, !is_r500
, rc_emulate_branches
, NULL
},
129 {"transform TEX", 1, 1, rc_local_transform
, rewrite_tex
},
130 {"native rewrite", 1, is_r500
, rc_local_transform
, native_rewrite_r500
},
131 {"native rewrite", 1, !is_r500
, rc_local_transform
, native_rewrite_r300
},
132 {"deadcode", 1, opt
, rc_dataflow_deadcode
, dataflow_outputs_mark_use
},
133 {"emulate loops", 1, !is_r500
, rc_emulate_loops
, NULL
},
134 {"dataflow optimize", 1, opt
, rc_optimize
, NULL
},
135 {"dataflow swizzles", 1, 1, rc_dataflow_swizzles
, NULL
},
136 {"dead constants", 1, kill_consts
, rc_remove_unused_constants
, &c
->code
->constants_remap_table
},
137 /* This pass makes it easier for the scheduler to group TEX
138 * instructions and reduces the chances of creating too
139 * many texture indirections.*/
140 {"register rename", 1, !is_r500
|| opt
, rc_rename_regs
, NULL
},
141 {"pair translate", 1, 1, rc_pair_translate
, NULL
},
142 {"pair scheduling", 1, 1, rc_pair_schedule
, NULL
},
143 {"register allocation", 1, opt
, rc_pair_regalloc
, NULL
},
144 {"dumb register allocation", 1, !opt
, rc_pair_regalloc_inputs_only
, NULL
},
145 {"final code validation", 0, 1, rc_validate_final_shader
, NULL
},
146 {"machine code generation", 0, is_r500
, r500BuildFragmentProgramHwCode
, NULL
},
147 {"machine code generation", 0, !is_r500
, r300BuildFragmentProgramHwCode
, NULL
},
148 {"dump machine code", 0, is_r500
&& (c
->Base
.Debug
& RC_DBG_LOG
), r500FragmentProgramDump
, NULL
},
149 {"dump machine code", 0, !is_r500
&& (c
->Base
.Debug
& RC_DBG_LOG
), r300FragmentProgramDump
, NULL
},
150 {NULL
, 0, 0, NULL
, NULL
}
153 c
->Base
.SwizzleCaps
= c
->Base
.is_r500
? &r500_swizzle_caps
: &r300_swizzle_caps
;
155 rc_run_compiler(&c
->Base
, fs_list
, "Fragment Program");
157 rc_constants_copy(&c
->code
->constants
, &c
->Base
.Program
.Constants
);