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 static int radeon_saturate_output(
82 struct radeon_compiler
* c
,
83 struct rc_instruction
* inst
,
86 const struct rc_opcode_info
*info
= rc_get_opcode_info(inst
->U
.I
.Opcode
);
88 if (!info
->HasDstReg
|| inst
->U
.I
.DstReg
.File
!= RC_FILE_OUTPUT
)
91 inst
->U
.I
.SaturateMode
= RC_SATURATE_ZERO_ONE
;
95 void r3xx_compile_fragment_program(struct r300_fragment_program_compiler
* c
)
97 int is_r500
= c
->Base
.is_r500
;
98 int opt
= !c
->Base
.disable_optimizations
;
99 int sat_out
= c
->state
.frag_clamp
;
101 /* Lists of instruction transformations. */
102 struct radeon_program_transformation saturate_output
[] = {
103 { &radeon_saturate_output
, c
},
107 struct radeon_program_transformation rewrite_tex
[] = {
108 { &radeonTransformTEX
, c
},
112 struct radeon_program_transformation native_rewrite_r500
[] = {
113 { &r500_transform_IF
, 0 },
114 { &radeonTransformALU
, 0 },
115 { &radeonTransformDeriv
, 0 },
116 { &radeonTransformTrigScale
, 0 },
120 struct radeon_program_transformation native_rewrite_r300
[] = {
121 { &radeonTransformALU
, 0 },
122 { &r300_transform_trig_simple
, 0 },
126 /* List of compiler passes. */
127 struct radeon_compiler_pass fs_list
[] = {
128 /* NAME DUMP PREDICATE FUNCTION PARAM */
129 {"rewrite depth out", 1, 1, rc_rewrite_depth_out
, NULL
},
130 /* This transformation needs to be done before any of the IF
131 * instructions are modified. */
132 {"transform KILP", 1, 1, rc_transform_KILP
, NULL
},
133 {"unroll loops", 1, is_r500
, rc_unroll_loops
, NULL
},
134 {"transform loops", 1, !is_r500
, rc_transform_loops
, NULL
},
135 {"emulate branches", 1, !is_r500
, rc_emulate_branches
, NULL
},
136 {"saturate output writes", 1, sat_out
, rc_local_transform
, saturate_output
},
137 {"transform TEX", 1, 1, rc_local_transform
, rewrite_tex
},
138 {"native rewrite", 1, is_r500
, rc_local_transform
, native_rewrite_r500
},
139 {"native rewrite", 1, !is_r500
, rc_local_transform
, native_rewrite_r300
},
140 {"deadcode", 1, opt
, rc_dataflow_deadcode
, dataflow_outputs_mark_use
},
141 {"emulate loops", 1, !is_r500
, rc_emulate_loops
, NULL
},
142 {"dataflow optimize", 1, opt
, rc_optimize
, NULL
},
143 {"dataflow swizzles", 1, 1, rc_dataflow_swizzles
, NULL
},
144 {"dead constants", 1, 1, rc_remove_unused_constants
, &c
->code
->constants_remap_table
},
145 /* This pass makes it easier for the scheduler to group TEX
146 * instructions and reduces the chances of creating too
147 * many texture indirections.*/
148 {"register rename", 1, !is_r500
, rc_rename_regs
, NULL
},
149 {"pair translate", 1, 1, rc_pair_translate
, NULL
},
150 {"pair scheduling", 1, 1, rc_pair_schedule
, NULL
},
151 {"dead sources", 1, 1, rc_pair_remove_dead_sources
, NULL
},
152 {"register allocation", 1, 1, rc_pair_regalloc
, opt
},
153 {"final code validation", 0, 1, rc_validate_final_shader
, NULL
},
154 {"machine code generation", 0, is_r500
, r500BuildFragmentProgramHwCode
, NULL
},
155 {"machine code generation", 0, !is_r500
, r300BuildFragmentProgramHwCode
, NULL
},
156 {"dump machine code", 0, is_r500
&& (c
->Base
.Debug
& RC_DBG_LOG
), r500FragmentProgramDump
, NULL
},
157 {"dump machine code", 0, !is_r500
&& (c
->Base
.Debug
& RC_DBG_LOG
), r300FragmentProgramDump
, NULL
},
158 {NULL
, 0, 0, NULL
, NULL
}
161 c
->Base
.type
= RC_FRAGMENT_PROGRAM
;
162 c
->Base
.SwizzleCaps
= c
->Base
.is_r500
? &r500_swizzle_caps
: &r300_swizzle_caps
;
164 rc_run_compiler(&c
->Base
, fs_list
);
166 rc_constants_copy(&c
->code
->constants
, &c
->Base
.Program
.Constants
);