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_compiler_util.h"
28 #include "radeon_dataflow.h"
29 #include "radeon_emulate_branches.h"
30 #include "radeon_emulate_loops.h"
31 #include "radeon_program_alu.h"
32 #include "radeon_program_tex.h"
33 #include "radeon_rename_regs.h"
34 #include "radeon_remove_constants.h"
35 #include "r300_fragprog.h"
36 #include "r300_fragprog_swizzle.h"
37 #include "r500_fragprog.h"
40 static void dataflow_outputs_mark_use(void * userdata
, void * data
,
41 void (*callback
)(void *, unsigned int, unsigned int))
43 struct r300_fragment_program_compiler
* c
= userdata
;
44 callback(data
, c
->OutputColor
[0], RC_MASK_XYZW
);
45 callback(data
, c
->OutputColor
[1], RC_MASK_XYZW
);
46 callback(data
, c
->OutputColor
[2], RC_MASK_XYZW
);
47 callback(data
, c
->OutputColor
[3], RC_MASK_XYZW
);
48 callback(data
, c
->OutputDepth
, RC_MASK_W
);
51 static void rc_rewrite_depth_out(struct radeon_compiler
*cc
, void *user
)
53 struct r300_fragment_program_compiler
*c
= (struct r300_fragment_program_compiler
*)cc
;
54 struct rc_instruction
*rci
;
56 for (rci
= c
->Base
.Program
.Instructions
.Next
; rci
!= &c
->Base
.Program
.Instructions
; rci
= rci
->Next
) {
57 struct rc_sub_instruction
* inst
= &rci
->U
.I
;
59 const struct rc_opcode_info
*info
= rc_get_opcode_info(inst
->Opcode
);
61 if (inst
->DstReg
.File
!= RC_FILE_OUTPUT
|| inst
->DstReg
.Index
!= c
->OutputDepth
)
64 if (inst
->DstReg
.WriteMask
& RC_MASK_Z
) {
65 inst
->DstReg
.WriteMask
= RC_MASK_W
;
67 inst
->DstReg
.WriteMask
= 0;
71 if (!info
->IsComponentwise
) {
75 for (i
= 0; i
< info
->NumSrcRegs
; i
++) {
76 inst
->SrcReg
[i
] = lmul_swizzle(RC_SWIZZLE_ZZZZ
, inst
->SrcReg
[i
]);
81 void r3xx_compile_fragment_program(struct r300_fragment_program_compiler
* c
)
83 int is_r500
= c
->Base
.is_r500
;
84 int opt
= !c
->Base
.disable_optimizations
;
85 int alpha2one
= c
->state
.alpha_to_one
;
87 /* Lists of instruction transformations. */
88 struct radeon_program_transformation force_alpha_to_one
[] = {
89 { &rc_force_output_alpha_to_one
, c
},
93 struct radeon_program_transformation rewrite_tex
[] = {
94 { &radeonTransformTEX
, c
},
98 struct radeon_program_transformation rewrite_if
[] = {
99 { &r500_transform_IF
, 0 },
103 struct radeon_program_transformation native_rewrite_r500
[] = {
104 { &radeonTransformALU
, 0 },
105 { &radeonTransformDeriv
, 0 },
106 { &radeonTransformTrigScale
, 0 },
110 struct radeon_program_transformation native_rewrite_r300
[] = {
111 { &radeonTransformALU
, 0 },
112 { &r300_transform_trig_simple
, 0 },
116 /* List of compiler passes. */
117 struct radeon_compiler_pass fs_list
[] = {
118 /* NAME DUMP PREDICATE FUNCTION PARAM */
119 {"rewrite depth out", 1, 1, rc_rewrite_depth_out
, NULL
},
120 /* This transformation needs to be done before any of the IF
121 * instructions are modified. */
122 {"transform KILP", 1, 1, rc_transform_KILP
, NULL
},
123 {"unroll loops", 1, is_r500
, rc_unroll_loops
, NULL
},
124 {"transform loops", 1, !is_r500
, rc_transform_loops
, NULL
},
125 {"emulate branches", 1, !is_r500
, rc_emulate_branches
, NULL
},
126 {"force alpha to one", 1, alpha2one
, rc_local_transform
, force_alpha_to_one
},
127 {"transform TEX", 1, 1, rc_local_transform
, rewrite_tex
},
128 {"transform IF", 1, is_r500
, rc_local_transform
, rewrite_if
},
129 {"native rewrite", 1, is_r500
, rc_local_transform
, native_rewrite_r500
},
130 {"native rewrite", 1, !is_r500
, rc_local_transform
, native_rewrite_r300
},
131 {"deadcode", 1, opt
, rc_dataflow_deadcode
, dataflow_outputs_mark_use
},
132 {"emulate loops", 1, !is_r500
, rc_emulate_loops
, NULL
},
133 {"register rename", 1, !is_r500
|| opt
, rc_rename_regs
, NULL
},
134 {"dataflow optimize", 1, opt
, rc_optimize
, NULL
},
135 {"inline literals", 1, is_r500
&& opt
, rc_inline_literals
, NULL
},
136 {"dataflow swizzles", 1, 1, rc_dataflow_swizzles
, NULL
},
137 {"dead constants", 1, 1, rc_remove_unused_constants
, &c
->code
->constants_remap_table
},
138 {"pair translate", 1, 1, rc_pair_translate
, NULL
},
139 {"pair scheduling", 1, 1, rc_pair_schedule
, &opt
},
140 {"dead sources", 1, 1, rc_pair_remove_dead_sources
, NULL
},
141 {"register allocation", 1, 1, rc_pair_regalloc
, &opt
},
142 {"final code validation", 0, 1, rc_validate_final_shader
, NULL
},
143 {"machine code generation", 0, is_r500
, r500BuildFragmentProgramHwCode
, NULL
},
144 {"machine code generation", 0, !is_r500
, r300BuildFragmentProgramHwCode
, NULL
},
145 {"dump machine code", 0, is_r500
&& (c
->Base
.Debug
& RC_DBG_LOG
), r500FragmentProgramDump
, NULL
},
146 {"dump machine code", 0, !is_r500
&& (c
->Base
.Debug
& RC_DBG_LOG
), r300FragmentProgramDump
, NULL
},
147 {NULL
, 0, 0, NULL
, NULL
}
150 c
->Base
.type
= RC_FRAGMENT_PROGRAM
;
151 c
->Base
.SwizzleCaps
= c
->Base
.is_r500
? &r500_swizzle_caps
: &r300_swizzle_caps
;
153 rc_run_compiler(&c
->Base
, fs_list
);
155 rc_constants_copy(&c
->code
->constants
, &c
->Base
.Program
.Constants
);