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_validate(struct nvc0_context
*nvc0
, struct nvc0_program
*prog
)
39 prog
->translated
= nvc0_program_translate(prog
);
40 if (!prog
->translated
)
43 size
= align(prog
->code_size
+ NVC0_SHADER_HEADER_SIZE
, 0x100);
45 ret
= nouveau_resource_alloc(nvc0
->screen
->text_heap
, size
, prog
,
50 prog
->code_base
= prog
->res
->start
;
52 nvc0_m2mf_push_linear(nvc0
, nvc0
->screen
->text
, NOUVEAU_BO_VRAM
,
53 prog
->code_base
, NVC0_SHADER_HEADER_SIZE
, prog
->hdr
);
54 nvc0_m2mf_push_linear(nvc0
, nvc0
->screen
->text
, NOUVEAU_BO_VRAM
,
55 prog
->code_base
+ NVC0_SHADER_HEADER_SIZE
,
56 prog
->code_size
, prog
->code
);
58 BEGIN_RING(nvc0
->screen
->base
.channel
, RING_3D(MEM_BARRIER
), 1);
59 OUT_RING (nvc0
->screen
->base
.channel
, 0x1111);
65 nvc0_vertprog_validate(struct nvc0_context
*nvc0
)
67 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
68 struct nvc0_program
*vp
= nvc0
->vertprog
;
70 if (nvc0
->clip
.nr
> vp
->vp
.num_ucps
) {
71 assert(nvc0
->clip
.nr
<= 6);
75 nvc0_program_destroy(nvc0
, vp
);
78 if (!nvc0_program_validate(nvc0
, vp
))
81 BEGIN_RING(chan
, RING_3D(SP_SELECT(1)), 2);
82 OUT_RING (chan
, 0x11);
83 OUT_RING (chan
, vp
->code_base
);
84 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(1)), 1);
85 OUT_RING (chan
, vp
->max_gpr
);
87 // BEGIN_RING(chan, RING_3D_(0x163c), 1);
88 // OUT_RING (chan, 0);
89 BEGIN_RING(chan
, RING_3D(VERT_COLOR_CLAMP_EN
), 1);
94 nvc0_fragprog_validate(struct nvc0_context
*nvc0
)
96 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
97 struct nvc0_program
*fp
= nvc0
->fragprog
;
99 if (!nvc0_program_validate(nvc0
, fp
))
102 BEGIN_RING(chan
, RING_3D(EARLY_FRAGMENT_TESTS
), 1);
103 OUT_RING (chan
, fp
->fp
.early_z
);
104 BEGIN_RING(chan
, RING_3D(SP_SELECT(5)), 2);
105 OUT_RING (chan
, 0x51);
106 OUT_RING (chan
, fp
->code_base
);
107 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(5)), 1);
108 OUT_RING (chan
, fp
->max_gpr
);
110 BEGIN_RING(chan
, RING_3D_(0x0360), 2);
111 OUT_RING (chan
, 0x20164010);
112 OUT_RING (chan
, 0x20);
113 BEGIN_RING(chan
, RING_3D_(0x196c), 1);
114 OUT_RING (chan
, fp
->flags
[0]);
118 nvc0_tctlprog_validate(struct nvc0_context
*nvc0
)
120 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
121 struct nvc0_program
*tp
= nvc0
->tctlprog
;
124 BEGIN_RING(chan
, RING_3D(SP_SELECT(2)), 1);
125 OUT_RING (chan
, 0x20);
128 if (!nvc0_program_validate(nvc0
, tp
))
131 BEGIN_RING(chan
, RING_3D(SP_SELECT(2)), 2);
132 OUT_RING (chan
, 0x21);
133 OUT_RING (chan
, tp
->code_base
);
134 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(2)), 1);
135 OUT_RING (chan
, tp
->max_gpr
);
139 nvc0_tevlprog_validate(struct nvc0_context
*nvc0
)
141 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
142 struct nvc0_program
*tp
= nvc0
->tevlprog
;
145 BEGIN_RING(chan
, RING_3D(TEP_SELECT
), 1);
146 OUT_RING (chan
, 0x30);
149 if (!nvc0_program_validate(nvc0
, tp
))
152 BEGIN_RING(chan
, RING_3D(TEP_SELECT
), 1);
153 OUT_RING (chan
, 0x31);
154 BEGIN_RING(chan
, RING_3D(SP_START_ID(3)), 1);
155 OUT_RING (chan
, tp
->code_base
);
156 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(3)), 1);
157 OUT_RING (chan
, tp
->max_gpr
);
161 nvc0_gmtyprog_validate(struct nvc0_context
*nvc0
)
163 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
164 struct nvc0_program
*gp
= nvc0
->gmtyprog
;
167 BEGIN_RING(chan
, RING_3D(GP_SELECT
), 1);
168 OUT_RING (chan
, 0x40);
171 if (!nvc0_program_validate(nvc0
, gp
))
174 BEGIN_RING(chan
, RING_3D(GP_SELECT
), 1);
175 OUT_RING (chan
, 0x41);
176 BEGIN_RING(chan
, RING_3D(SP_START_ID(4)), 1);
177 OUT_RING (chan
, gp
->code_base
);
178 BEGIN_RING(chan
, RING_3D(SP_GPR_ALLOC(4)), 1);
179 OUT_RING (chan
, gp
->max_gpr
);
182 /* It's *is* kind of shader related. We need to inspect the program
183 * to get the output locations right.
186 nvc0_tfb_validate(struct nvc0_context
*nvc0
)
188 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
189 struct nvc0_program
*vp
;
190 struct nvc0_transform_feedback_state
*tfb
= nvc0
->tfb
;
193 BEGIN_RING(chan
, RING_3D(TFB_ENABLE
), 1);
200 vp
= nvc0
->vertprog
? nvc0
->vertprog
: nvc0
->gmtyprog
;
202 for (b
= 0; b
< nvc0
->num_tfbbufs
; ++b
) {
203 uint8_t idx
, var
[128];
205 struct nvc0_resource
*buf
= nvc0_resource(nvc0
->tfbbuf
[b
]);
207 BEGIN_RING(chan
, RING_3D(TFB_BUFFER_ENABLE(b
)), 5);
209 OUT_RESRCh(chan
, buf
, nvc0
->tfb_offset
[b
], NOUVEAU_BO_WR
);
210 OUT_RESRCl(chan
, buf
, nvc0
->tfb_offset
[b
], NOUVEAU_BO_WR
);
211 OUT_RING (chan
, buf
->base
.width0
- nvc0
->tfb_offset
[b
]);
212 OUT_RING (chan
, 0); /* TFB_PRIMITIVE_ID <- offset ? */
214 if (!(nvc0
->dirty
& NVC0_NEW_TFB
))
217 BEGIN_RING(chan
, RING_3D(TFB_UNK07X0(b
)), 3);
219 OUT_RING (chan
, tfb
->varying_count
[b
]);
220 OUT_RING (chan
, tfb
->stride
[b
]);
222 n
= b
? tfb
->varying_count
[b
- 1] : 0;
224 for (; i
< tfb
->varying_count
[b
]; ++i
) {
225 idx
= tfb
->varying_index
[n
+ i
];
226 var
[i
] = vp
->vp
.out_pos
[idx
>> 2] + (idx
& 3);
231 BEGIN_RING(chan
, RING_3D(TFB_VARYING_LOCS(b
, 0)), i
/ 4);
232 OUT_RINGp (chan
, var
, i
/ 4);
235 IMMED_RING(chan
, RING_3D(TFB_BUFFER_ENABLE(b
)), 0);