2 * Copyright 2012 Red Hat Inc.
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "draw/draw_context.h"
27 #include "util/u_dynarray.h"
28 #include "tgsi/tgsi_parse.h"
30 #include "nv_object.xml.h"
31 #include "nv30/nv30-40_3d.xml.h"
32 #include "nv30/nv30_context.h"
33 #include "nv30/nvfx_shader.h"
34 #include "nv30/nv30_state.h"
37 nv30_vertprog_destroy(struct nv30_vertprog
*vp
)
39 util_dynarray_fini(&vp
->branch_relocs
);
40 nouveau_heap_free(&vp
->exec
);
45 util_dynarray_fini(&vp
->const_relocs
);
46 nouveau_heap_free(&vp
->data
);
51 vp
->translated
= false;
55 nv30_vertprog_validate(struct nv30_context
*nv30
)
57 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
58 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
59 struct nv30_vertprog
*vp
= nv30
->vertprog
.program
;
60 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
61 bool upload_code
= false;
62 bool upload_data
= false;
65 if (nv30
->dirty
& NV30_NEW_FRAGPROG
) {
66 if (memcmp(vp
->texcoord
, fp
->texcoord
, sizeof(vp
->texcoord
))) {
68 nv30_vertprog_destroy(vp
);
69 memcpy(vp
->texcoord
, fp
->texcoord
, sizeof(vp
->texcoord
));
73 if (nv30
->rast
&& nv30
->rast
->pipe
.clip_plane_enable
!= vp
->enabled_ucps
) {
74 vp
->enabled_ucps
= nv30
->rast
->pipe
.clip_plane_enable
;
76 nv30_vertprog_destroy(vp
);
79 if (!vp
->translated
) {
80 vp
->translated
= _nvfx_vertprog_translate(eng3d
->oclass
, vp
);
81 if (!vp
->translated
) {
82 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
85 nv30
->dirty
|= NV30_NEW_VERTPROG
;
89 struct nouveau_heap
*heap
= nv30
->screen
->vp_exec_heap
;
90 struct nv30_shader_reloc
*reloc
= vp
->branch_relocs
.data
;
91 unsigned nr_reloc
= vp
->branch_relocs
.size
/ sizeof(*reloc
);
92 uint32_t *inst
, target
;
94 if (nouveau_heap_alloc(heap
, vp
->nr_insns
, &vp
->exec
, &vp
->exec
)) {
95 while (heap
->next
&& heap
->size
< vp
->nr_insns
) {
96 struct nouveau_heap
**evict
= heap
->next
->priv
;
97 nouveau_heap_free(evict
);
100 if (nouveau_heap_alloc(heap
, vp
->nr_insns
, &vp
->exec
, &vp
->exec
)) {
101 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
106 if (eng3d
->oclass
< NV40_3D_CLASS
) {
108 inst
= vp
->insns
[reloc
->location
].data
;
109 target
= vp
->exec
->start
+ reloc
->target
;
111 inst
[2] &= ~0x000007fc;
112 inst
[2] |= target
<< 2;
117 inst
= vp
->insns
[reloc
->location
].data
;
118 target
= vp
->exec
->start
+ reloc
->target
;
120 inst
[2] &= ~0x0000003f;
121 inst
[2] |= target
>> 3;
122 inst
[3] &= ~0xe0000000;
123 inst
[3] |= target
<< 29;
131 if (vp
->nr_consts
&& !vp
->data
) {
132 struct nouveau_heap
*heap
= nv30
->screen
->vp_data_heap
;
133 struct nv30_shader_reloc
*reloc
= vp
->const_relocs
.data
;
134 unsigned nr_reloc
= vp
->const_relocs
.size
/ sizeof(*reloc
);
135 uint32_t *inst
, target
;
137 if (nouveau_heap_alloc(heap
, vp
->nr_consts
, vp
, &vp
->data
)) {
138 while (heap
->next
&& heap
->size
< vp
->nr_consts
) {
139 struct nv30_vertprog
*evp
= heap
->next
->priv
;
140 nouveau_heap_free(&evp
->data
);
143 if (nouveau_heap_alloc(heap
, vp
->nr_consts
, vp
, &vp
->data
)) {
144 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
149 if (eng3d
->oclass
< NV40_3D_CLASS
) {
151 inst
= vp
->insns
[reloc
->location
].data
;
152 target
= vp
->data
->start
+ reloc
->target
;
154 inst
[1] &= ~0x0007fc000;
155 inst
[1] |= (target
& 0x1ff) << 14;
160 inst
= vp
->insns
[reloc
->location
].data
;
161 target
= vp
->data
->start
+ reloc
->target
;
163 inst
[1] &= ~0x0001ff000;
164 inst
[1] |= (target
& 0x1ff) << 12;
174 struct nv04_resource
*res
= nv04_resource(nv30
->vertprog
.constbuf
);
176 for (i
= 0; i
< vp
->nr_consts
; i
++) {
177 struct nv30_vertprog_data
*data
= &vp
->consts
[i
];
179 if (data
->index
< 0) {
183 float *constbuf
= (float *)res
->data
;
185 !memcmp(data
->value
, &constbuf
[data
->index
* 4], 16))
187 memcpy(data
->value
, &constbuf
[data
->index
* 4], 16);
190 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_CONST_ID
), 5);
191 PUSH_DATA (push
, vp
->data
->start
+ i
);
192 PUSH_DATAp(push
, data
->value
, 4);
197 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_FROM_ID
), 1);
198 PUSH_DATA (push
, vp
->exec
->start
);
199 for (i
= 0; i
< vp
->nr_insns
; i
++) {
200 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_INST(0)), 4);
201 PUSH_DATAp(push
, vp
->insns
[i
].data
, 4);
205 if (nv30
->dirty
& (NV30_NEW_VERTPROG
| NV30_NEW_FRAGPROG
)) {
206 BEGIN_NV04(push
, NV30_3D(VP_START_FROM_ID
), 1);
207 PUSH_DATA (push
, vp
->exec
->start
);
208 if (eng3d
->oclass
< NV40_3D_CLASS
) {
209 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
210 PUSH_DATA (push
, 0x00000013); /* vp instead of ff, somehow */
212 BEGIN_NV04(push
, NV40_3D(VP_ATTRIB_EN
), 2);
213 PUSH_DATA (push
, vp
->ir
);
214 PUSH_DATA (push
, vp
->or | fp
->vp_or
);
215 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
216 PUSH_DATA (push
, 0x00000011);
222 nv30_vp_state_create(struct pipe_context
*pipe
,
223 const struct pipe_shader_state
*cso
)
225 struct nv30_vertprog
*vp
= CALLOC_STRUCT(nv30_vertprog
);
229 vp
->pipe
.tokens
= tgsi_dup_tokens(cso
->tokens
);
230 tgsi_scan_shader(vp
->pipe
.tokens
, &vp
->info
);
235 nv30_vp_state_delete(struct pipe_context
*pipe
, void *hwcso
)
237 struct nv30_vertprog
*vp
= hwcso
;
240 nv30_vertprog_destroy(vp
);
243 draw_delete_vertex_shader(nv30_context(pipe
)->draw
, vp
->draw
);
245 FREE((void *)vp
->pipe
.tokens
);
250 nv30_vp_state_bind(struct pipe_context
*pipe
, void *hwcso
)
252 struct nv30_context
*nv30
= nv30_context(pipe
);
254 nv30
->vertprog
.program
= hwcso
;
255 nv30
->dirty
|= NV30_NEW_VERTPROG
;
259 nv30_vertprog_init(struct pipe_context
*pipe
)
261 pipe
->create_vs_state
= nv30_vp_state_create
;
262 pipe
->bind_vs_state
= nv30_vp_state_bind
;
263 pipe
->delete_vs_state
= nv30_vp_state_delete
;