2 * Copyright 2010 Christoph Bumiller
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include "pipe/p_context.h"
24 #include "pipe/p_defines.h"
25 #include "pipe/p_state.h"
26 #include "util/u_inlines.h"
28 #include "nvc0_context.h"
31 nvc0_program_update_context_state(struct nvc0_context
*nvc0
,
32 struct nvc0_program
*prog
, int stage
)
35 nvc0
->state
.tls_required
|= 1 << stage
;
37 nvc0
->state
.tls_required
&= ~(1 << stage
);
41 nvc0_program_validate(struct nvc0_context
*nvc0
, struct nvc0_program
*prog
)
49 prog
->translated
= nvc0_program_translate(prog
);
50 if (!prog
->translated
)
53 size
= align(prog
->code_size
+ NVC0_SHADER_HEADER_SIZE
, 0x100);
55 ret
= nouveau_resource_alloc(nvc0
->screen
->text_heap
, size
, prog
,
60 prog
->code_base
= prog
->res
->start
;
62 nvc0_m2mf_push_linear(&nvc0
->base
, nvc0
->screen
->text
, prog
->code_base
,
63 NOUVEAU_BO_VRAM
, NVC0_SHADER_HEADER_SIZE
, prog
->hdr
);
64 nvc0_m2mf_push_linear(&nvc0
->base
, nvc0
->screen
->text
,
65 prog
->code_base
+ NVC0_SHADER_HEADER_SIZE
,
66 NOUVEAU_BO_VRAM
, prog
->code_size
, prog
->code
);
68 BEGIN_RING(nvc0
->screen
->base
.channel
, RING_3D(MEM_BARRIER
), 1);
69 OUT_RING (nvc0
->screen
->base
.channel
, 0x1111);
75 nvc0_vertprog_validate(struct nvc0_context
*nvc0
)
77 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
78 struct nvc0_program
*vp
= nvc0
->vertprog
;
80 if (nvc0
->clip
.nr
> vp
->vp
.num_ucps
) {
81 assert(nvc0
->clip
.nr
<= 6);
85 nvc0_program_destroy(nvc0
, vp
);
88 if (!nvc0_program_validate(nvc0
, vp
))
90 nvc0_program_update_context_state(nvc0
, vp
, 0);
92 BEGIN_RING(chan
, RING_3D(SP_SELECT(1)), 2);
93 OUT_RING (chan
, 0x11);
94 OUT_RING (chan
, vp
->code_base
);
95 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(1)), 1);
96 OUT_RING (chan
, vp
->max_gpr
);
98 // BEGIN_RING(chan, RING_3D_(0x163c), 1);
99 // OUT_RING (chan, 0);
103 nvc0_fragprog_validate(struct nvc0_context
*nvc0
)
105 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
106 struct nvc0_program
*fp
= nvc0
->fragprog
;
108 if (!nvc0_program_validate(nvc0
, fp
))
110 nvc0_program_update_context_state(nvc0
, fp
, 4);
112 BEGIN_RING(chan
, RING_3D(SP_SELECT(5)), 2);
113 OUT_RING (chan
, 0x51);
114 OUT_RING (chan
, fp
->code_base
);
115 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(5)), 1);
116 OUT_RING (chan
, fp
->max_gpr
);
118 BEGIN_RING(chan
, RING_3D_(0x0360), 2);
119 OUT_RING (chan
, 0x20164010);
120 OUT_RING (chan
, 0x20);
121 BEGIN_RING(chan
, RING_3D_(0x196c), 1);
122 OUT_RING (chan
, fp
->flags
[0]);
126 nvc0_tctlprog_validate(struct nvc0_context
*nvc0
)
128 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
129 struct nvc0_program
*tp
= nvc0
->tctlprog
;
132 BEGIN_RING(chan
, RING_3D(SP_SELECT(2)), 1);
133 OUT_RING (chan
, 0x20);
136 if (!nvc0_program_validate(nvc0
, tp
))
138 nvc0_program_update_context_state(nvc0
, tp
, 1);
140 BEGIN_RING(chan
, RING_3D(SP_SELECT(2)), 2);
141 OUT_RING (chan
, 0x21);
142 OUT_RING (chan
, tp
->code_base
);
143 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(2)), 1);
144 OUT_RING (chan
, tp
->max_gpr
);
148 nvc0_tevlprog_validate(struct nvc0_context
*nvc0
)
150 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
151 struct nvc0_program
*tp
= nvc0
->tevlprog
;
154 BEGIN_RING(chan
, RING_3D(TEP_SELECT
), 1);
155 OUT_RING (chan
, 0x30);
158 if (!nvc0_program_validate(nvc0
, tp
))
160 nvc0_program_update_context_state(nvc0
, tp
, 2);
162 BEGIN_RING(chan
, RING_3D(TEP_SELECT
), 1);
163 OUT_RING (chan
, 0x31);
164 BEGIN_RING(chan
, RING_3D(SP_START_ID(3)), 1);
165 OUT_RING (chan
, tp
->code_base
);
166 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(3)), 1);
167 OUT_RING (chan
, tp
->max_gpr
);
171 nvc0_gmtyprog_validate(struct nvc0_context
*nvc0
)
173 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
174 struct nvc0_program
*gp
= nvc0
->gmtyprog
;
177 BEGIN_RING(chan
, RING_3D(GP_SELECT
), 1);
178 OUT_RING (chan
, 0x40);
181 if (!nvc0_program_validate(nvc0
, gp
))
183 nvc0_program_update_context_state(nvc0
, gp
, 3);
185 BEGIN_RING(chan
, RING_3D(GP_SELECT
), 1);
186 OUT_RING (chan
, 0x41);
187 BEGIN_RING(chan
, RING_3D(SP_START_ID(4)), 1);
188 OUT_RING (chan
, gp
->code_base
);
189 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(4)), 1);
190 OUT_RING (chan
, gp
->max_gpr
);
193 /* It's *is* kind of shader related. We need to inspect the program
194 * to get the output locations right.
197 nvc0_tfb_validate(struct nvc0_context
*nvc0
)
199 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
200 struct nvc0_program
*vp
;
201 struct nvc0_transform_feedback_state
*tfb
= nvc0
->tfb
;
204 BEGIN_RING(chan
, RING_3D(TFB_ENABLE
), 1);
211 vp
= nvc0
->vertprog
? nvc0
->vertprog
: nvc0
->gmtyprog
;
213 for (b
= 0; b
< nvc0
->num_tfbbufs
; ++b
) {
214 uint8_t idx
, var
[128];
216 struct nv04_resource
*buf
= nv04_resource(nvc0
->tfbbuf
[b
]);
218 BEGIN_RING(chan
, RING_3D(TFB_BUFFER_ENABLE(b
)), 5);
220 OUT_RESRCh(chan
, buf
, nvc0
->tfb_offset
[b
], NOUVEAU_BO_WR
);
221 OUT_RESRCl(chan
, buf
, nvc0
->tfb_offset
[b
], NOUVEAU_BO_WR
);
222 OUT_RING (chan
, buf
->base
.width0
- nvc0
->tfb_offset
[b
]);
223 OUT_RING (chan
, 0); /* TFB_PRIMITIVE_ID <- offset ? */
225 if (!(nvc0
->dirty
& NVC0_NEW_TFB
))
228 BEGIN_RING(chan
, RING_3D(TFB_UNK07X0(b
)), 3);
230 OUT_RING (chan
, tfb
->varying_count
[b
]);
231 OUT_RING (chan
, tfb
->stride
[b
]);
233 n
= b
? tfb
->varying_count
[b
- 1] : 0;
235 for (; i
< tfb
->varying_count
[b
]; ++i
) {
236 idx
= tfb
->varying_index
[n
+ i
];
237 var
[i
] = vp
->vp
.out_pos
[idx
>> 2] + (idx
& 3);
242 BEGIN_RING(chan
, RING_3D(TFB_VARYING_LOCS(b
, 0)), i
/ 4);
243 OUT_RINGp (chan
, var
, i
/ 4);
246 IMMED_RING(chan
, RING_3D(TFB_BUFFER_ENABLE(b
)), 0);