2 * Copyright (C) 2015 Advanced Micro Devices, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "tgsi/tgsi_transform.h"
27 #include "tgsi/tgsi_scan.h"
28 #include "tgsi/tgsi_dump.h"
29 #include "util/u_debug.h"
31 #include "tgsi_emulate.h"
33 struct tgsi_emulation_context
{
34 struct tgsi_transform_context base
;
35 struct tgsi_shader_info info
;
37 bool first_instruction_emitted
;
40 static inline struct tgsi_emulation_context
*
41 tgsi_emulation_context(struct tgsi_transform_context
*tctx
)
43 return (struct tgsi_emulation_context
*)tctx
;
47 transform_decl(struct tgsi_transform_context
*tctx
,
48 struct tgsi_full_declaration
*decl
)
50 struct tgsi_emulation_context
*ctx
= tgsi_emulation_context(tctx
);
52 if (ctx
->flags
& TGSI_EMU_FORCE_PERSAMPLE_INTERP
&&
53 decl
->Declaration
.File
== TGSI_FILE_INPUT
) {
54 assert(decl
->Declaration
.Interpolate
);
55 decl
->Interp
.Location
= TGSI_INTERPOLATE_LOC_SAMPLE
;
58 tctx
->emit_declaration(tctx
, decl
);
62 passthrough_edgeflag(struct tgsi_transform_context
*tctx
)
64 struct tgsi_emulation_context
*ctx
= tgsi_emulation_context(tctx
);
65 struct tgsi_full_declaration decl
;
66 struct tgsi_full_instruction new_inst
;
69 decl
= tgsi_default_full_declaration();
70 decl
.Declaration
.File
= TGSI_FILE_INPUT
;
71 decl
.Range
.First
= decl
.Range
.Last
= ctx
->info
.num_inputs
;
72 tctx
->emit_declaration(tctx
, &decl
);
75 decl
= tgsi_default_full_declaration();
76 decl
.Declaration
.File
= TGSI_FILE_OUTPUT
;
77 decl
.Declaration
.Semantic
= true;
78 decl
.Range
.First
= decl
.Range
.Last
= ctx
->info
.num_outputs
;
79 decl
.Semantic
.Name
= TGSI_SEMANTIC_EDGEFLAG
;
80 decl
.Semantic
.Index
= 0;
81 tctx
->emit_declaration(tctx
, &decl
);
84 new_inst
= tgsi_default_full_instruction();
85 new_inst
.Instruction
.Opcode
= TGSI_OPCODE_MOV
;
87 new_inst
.Instruction
.NumDstRegs
= 1;
88 new_inst
.Dst
[0].Register
.File
= TGSI_FILE_OUTPUT
;
89 new_inst
.Dst
[0].Register
.Index
= ctx
->info
.num_outputs
;
90 new_inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
92 new_inst
.Instruction
.NumSrcRegs
= 1;
93 new_inst
.Src
[0].Register
.File
= TGSI_FILE_INPUT
;
94 new_inst
.Src
[0].Register
.Index
= ctx
->info
.num_inputs
;
95 new_inst
.Src
[0].Register
.SwizzleX
= TGSI_SWIZZLE_X
;
96 new_inst
.Src
[0].Register
.SwizzleY
= TGSI_SWIZZLE_X
;
97 new_inst
.Src
[0].Register
.SwizzleZ
= TGSI_SWIZZLE_X
;
98 new_inst
.Src
[0].Register
.SwizzleW
= TGSI_SWIZZLE_X
;
100 tctx
->emit_instruction(tctx
, &new_inst
);
104 transform_instr(struct tgsi_transform_context
*tctx
,
105 struct tgsi_full_instruction
*inst
)
107 struct tgsi_emulation_context
*ctx
= tgsi_emulation_context(tctx
);
109 /* Pass through edgeflags. */
110 if (!ctx
->first_instruction_emitted
) {
111 ctx
->first_instruction_emitted
= true;
113 if (ctx
->flags
& TGSI_EMU_PASSTHROUGH_EDGEFLAG
)
114 passthrough_edgeflag(tctx
);
117 /* Clamp color outputs. */
118 if (ctx
->flags
& TGSI_EMU_CLAMP_COLOR_OUTPUTS
) {
120 for (i
= 0; i
< inst
->Instruction
.NumDstRegs
; i
++) {
123 if (inst
->Dst
[i
].Register
.File
!= TGSI_FILE_OUTPUT
||
124 inst
->Dst
[i
].Register
.Indirect
)
128 ctx
->info
.output_semantic_name
[inst
->Dst
[i
].Register
.Index
];
130 if (semantic
== TGSI_SEMANTIC_COLOR
||
131 semantic
== TGSI_SEMANTIC_BCOLOR
)
132 inst
->Instruction
.Saturate
= true;
136 tctx
->emit_instruction(tctx
, inst
);
139 const struct tgsi_token
*
140 tgsi_emulate(const struct tgsi_token
*tokens
, unsigned flags
)
142 struct tgsi_emulation_context ctx
;
143 struct tgsi_token
*newtoks
;
146 if (!(flags
& (TGSI_EMU_CLAMP_COLOR_OUTPUTS
|
147 TGSI_EMU_PASSTHROUGH_EDGEFLAG
|
148 TGSI_EMU_FORCE_PERSAMPLE_INTERP
)))
151 memset(&ctx
, 0, sizeof(ctx
));
153 tgsi_scan_shader(tokens
, &ctx
.info
);
155 if (flags
& TGSI_EMU_FORCE_PERSAMPLE_INTERP
)
156 ctx
.base
.transform_declaration
= transform_decl
;
158 if (flags
& (TGSI_EMU_CLAMP_COLOR_OUTPUTS
|
159 TGSI_EMU_PASSTHROUGH_EDGEFLAG
))
160 ctx
.base
.transform_instruction
= transform_instr
;
162 newlen
= tgsi_num_tokens(tokens
) + 20;
163 newtoks
= tgsi_alloc_tokens(newlen
);
167 tgsi_transform_shader(tokens
, newtoks
, newlen
, &ctx
.base
);