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 "util/u_dynarray.h"
27 #include "tgsi/tgsi_parse.h"
29 #include "nv_object.xml.h"
30 #include "nv30/nv30-40_3d.xml.h"
31 #include "nv30/nv30_context.h"
32 #include "nv30/nvfx_shader.h"
33 #include "nv30/nv30_state.h"
36 nv30_vertprog_destroy(struct nv30_vertprog
*vp
)
38 util_dynarray_fini(&vp
->branch_relocs
);
39 nouveau_heap_free(&vp
->exec
);
44 util_dynarray_fini(&vp
->const_relocs
);
45 nouveau_heap_free(&vp
->data
);
50 vp
->translated
= FALSE
;
54 nv30_vertprog_validate(struct nv30_context
*nv30
)
56 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
57 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
58 struct nv30_vertprog
*vp
= nv30
->vertprog
.program
;
59 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
60 boolean upload_code
= FALSE
;
61 boolean upload_data
= FALSE
;
64 if (nv30
->dirty
& NV30_NEW_FRAGPROG
) {
65 if (memcmp(vp
->texcoord
, fp
->texcoord
, sizeof(vp
->texcoord
))) {
67 nv30_vertprog_destroy(vp
);
68 memcpy(vp
->texcoord
, fp
->texcoord
, sizeof(vp
->texcoord
));
72 if (nv30
->rast
&& nv30
->rast
->pipe
.clip_plane_enable
!= vp
->enabled_ucps
) {
73 vp
->enabled_ucps
= nv30
->rast
->pipe
.clip_plane_enable
;
75 nv30_vertprog_destroy(vp
);
78 if (!vp
->translated
) {
79 vp
->translated
= _nvfx_vertprog_translate(eng3d
->oclass
, vp
);
80 if (!vp
->translated
) {
81 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
84 nv30
->dirty
|= NV30_NEW_VERTPROG
;
88 struct nouveau_heap
*heap
= nv30
->screen
->vp_exec_heap
;
89 struct nv30_shader_reloc
*reloc
= vp
->branch_relocs
.data
;
90 unsigned nr_reloc
= vp
->branch_relocs
.size
/ sizeof(*reloc
);
91 uint32_t *inst
, target
;
93 if (nouveau_heap_alloc(heap
, vp
->nr_insns
, &vp
->exec
, &vp
->exec
)) {
94 while (heap
->next
&& heap
->size
< vp
->nr_insns
) {
95 struct nouveau_heap
**evict
= heap
->next
->priv
;
96 nouveau_heap_free(evict
);
99 if (nouveau_heap_alloc(heap
, vp
->nr_insns
, &vp
->exec
, &vp
->exec
)) {
100 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
105 if (eng3d
->oclass
< NV40_3D_CLASS
) {
107 inst
= vp
->insns
[reloc
->location
].data
;
108 target
= vp
->exec
->start
+ reloc
->target
;
110 inst
[2] &= ~0x000007fc;
111 inst
[2] |= target
<< 2;
116 inst
= vp
->insns
[reloc
->location
].data
;
117 target
= vp
->exec
->start
+ reloc
->target
;
119 inst
[2] &= ~0x0000003f;
120 inst
[2] |= target
>> 3;
121 inst
[3] &= ~0xe0000000;
122 inst
[3] |= target
<< 29;
130 if (vp
->nr_consts
&& !vp
->data
) {
131 struct nouveau_heap
*heap
= nv30
->screen
->vp_data_heap
;
132 struct nv30_shader_reloc
*reloc
= vp
->const_relocs
.data
;
133 unsigned nr_reloc
= vp
->const_relocs
.size
/ sizeof(*reloc
);
134 uint32_t *inst
, target
;
136 if (nouveau_heap_alloc(heap
, vp
->nr_consts
, vp
, &vp
->data
)) {
137 while (heap
->next
&& heap
->size
< vp
->nr_consts
) {
138 struct nv30_vertprog
*evp
= heap
->next
->priv
;
139 nouveau_heap_free(&evp
->data
);
142 if (nouveau_heap_alloc(heap
, vp
->nr_consts
, vp
, &vp
->data
)) {
143 nv30
->draw_flags
|= NV30_NEW_VERTPROG
;
148 if (eng3d
->oclass
< NV40_3D_CLASS
) {
150 inst
= vp
->insns
[reloc
->location
].data
;
151 target
= vp
->data
->start
+ reloc
->target
;
153 inst
[1] &= ~0x0007fc000;
154 inst
[1] |= (target
& 0x1ff) << 14;
159 inst
= vp
->insns
[reloc
->location
].data
;
160 target
= vp
->data
->start
+ reloc
->target
;
162 inst
[1] &= ~0x0001ff000;
163 inst
[1] |= (target
& 0x1ff) << 12;
173 struct nv04_resource
*res
= nv04_resource(nv30
->vertprog
.constbuf
);
175 for (i
= 0; i
< vp
->nr_consts
; i
++) {
176 struct nv30_vertprog_data
*data
= &vp
->consts
[i
];
178 if (data
->index
< 0) {
182 float *constbuf
= (float *)res
->data
;
184 !memcmp(data
->value
, &constbuf
[data
->index
* 4], 16))
186 memcpy(data
->value
, &constbuf
[data
->index
* 4], 16);
189 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_CONST_ID
), 5);
190 PUSH_DATA (push
, vp
->data
->start
+ i
);
191 PUSH_DATAp(push
, data
->value
, 4);
196 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_FROM_ID
), 1);
197 PUSH_DATA (push
, vp
->exec
->start
);
198 for (i
= 0; i
< vp
->nr_insns
; i
++) {
199 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_INST(0)), 4);
200 PUSH_DATAp(push
, vp
->insns
[i
].data
, 4);
204 if (nv30
->dirty
& (NV30_NEW_VERTPROG
| NV30_NEW_FRAGPROG
)) {
205 BEGIN_NV04(push
, NV30_3D(VP_START_FROM_ID
), 1);
206 PUSH_DATA (push
, vp
->exec
->start
);
207 if (eng3d
->oclass
< NV40_3D_CLASS
) {
208 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
209 PUSH_DATA (push
, 0x00000013); /* vp instead of ff, somehow */
211 BEGIN_NV04(push
, NV40_3D(VP_ATTRIB_EN
), 2);
212 PUSH_DATA (push
, vp
->ir
);
213 PUSH_DATA (push
, vp
->or | fp
->vp_or
);
214 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
215 PUSH_DATA (push
, 0x00000011);
221 nv30_vp_state_create(struct pipe_context
*pipe
,
222 const struct pipe_shader_state
*cso
)
224 struct nv30_vertprog
*vp
= CALLOC_STRUCT(nv30_vertprog
);
228 vp
->pipe
.tokens
= tgsi_dup_tokens(cso
->tokens
);
229 tgsi_scan_shader(vp
->pipe
.tokens
, &vp
->info
);
234 nv30_vp_state_delete(struct pipe_context
*pipe
, void *hwcso
)
236 struct nv30_vertprog
*vp
= hwcso
;
239 nv30_vertprog_destroy(vp
);
240 FREE((void *)vp
->pipe
.tokens
);
245 nv30_vp_state_bind(struct pipe_context
*pipe
, void *hwcso
)
247 struct nv30_context
*nv30
= nv30_context(pipe
);
249 nv30
->vertprog
.program
= hwcso
;
250 nv30
->dirty
|= NV30_NEW_VERTPROG
;
254 nv30_vertprog_init(struct pipe_context
*pipe
)
256 pipe
->create_vs_state
= nv30_vp_state_create
;
257 pipe
->bind_vs_state
= nv30_vp_state_bind
;
258 pipe
->delete_vs_state
= nv30_vp_state_delete
;