2 * shaders implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader
);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
34 /* Shader debugging - Change the following line to enable debugging of software
36 #if 0 /* Musxt not be 1 in cvs version */
37 # define VSTRACE(A) TRACE A
38 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
41 # define TRACE_VSVECTOR(name)
44 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
47 * DirectX9 SDK download
48 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
51 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
53 * Using Vertex Shaders
54 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
57 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
60 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
61 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
62 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
63 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
66 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
69 * http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
71 * NVIDIA: DX8 Vertex Shader to NV Vertex Program
72 * http://developer.nvidia.com/view.asp?IO=vstovp
74 * NVIDIA: Memory Management with VAR
75 * http://developer.nvidia.com/view.asp?IO=var_memory_management
78 /* TODO: Vertex and Pixel shaders are almost identicle, the only exception being the way that some of the data is looked up or the availablity of some of the data i.e. some instructions are only valid for pshaders and some for vshaders
79 because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't supprise me if the programes can be cross compiled using a large body body shared code */
81 #define GLNAME_REQUIRE_GLSL ((const char *)1)
83 /*******************************
84 * vshader functions software VM
87 void vshader_add(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
92 VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
93 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
96 void vshader_dp3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
97 d
->x
= d
->y
= d
->z
= d
->w
= s0
->x
* s1
->x
+ s0
->y
* s1
->y
+ s0
->z
* s1
->z
;
98 VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
99 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
102 void vshader_dp4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
103 d
->x
= d
->y
= d
->z
= d
->w
= s0
->x
* s1
->x
+ s0
->y
* s1
->y
+ s0
->z
* s1
->z
+ s0
->w
* s1
->w
;
104 VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
105 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
108 void vshader_dst(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
110 d
->y
= s0
->y
* s1
->y
;
113 VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
114 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
117 void vshader_expp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
123 tmp
.f
= floorf(s0
->w
);
124 d
->x
= powf(2.0f
, tmp
.f
);
125 d
->y
= s0
->w
- tmp
.f
;
126 tmp
.f
= powf(2.0f
, s0
->w
);
127 tmp
.d
&= 0xFFFFFF00U
;
130 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
131 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
134 void vshader_lit(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
136 d
->y
= (0.0f
< s0
->x
) ? s0
->x
: 0.0f
;
137 d
->z
= (0.0f
< s0
->x
&& 0.0f
< s0
->y
) ? powf(s0
->y
, s0
->w
) : 0.0f
;
139 VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
140 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
143 void vshader_logp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
144 float tmp_f
= fabsf(s0
->w
);
145 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
!= tmp_f
) ? logf(tmp_f
) / logf(2.0f
) : -HUGE_VAL
;
146 VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
147 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
150 void vshader_mad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
151 d
->x
= s0
->x
* s1
->x
+ s2
->x
;
152 d
->y
= s0
->y
* s1
->y
+ s2
->y
;
153 d
->z
= s0
->z
* s1
->z
+ s2
->z
;
154 d
->w
= s0
->w
* s1
->w
+ s2
->w
;
155 VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
156 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, s2
->x
, s2
->y
, s2
->z
, s2
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
159 void vshader_max(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
160 d
->x
= (s0
->x
>= s1
->x
) ? s0
->x
: s1
->x
;
161 d
->y
= (s0
->y
>= s1
->y
) ? s0
->y
: s1
->y
;
162 d
->z
= (s0
->z
>= s1
->z
) ? s0
->z
: s1
->z
;
163 d
->w
= (s0
->w
>= s1
->w
) ? s0
->w
: s1
->w
;
164 VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
165 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
168 void vshader_min(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
169 d
->x
= (s0
->x
< s1
->x
) ? s0
->x
: s1
->x
;
170 d
->y
= (s0
->y
< s1
->y
) ? s0
->y
: s1
->y
;
171 d
->z
= (s0
->z
< s1
->z
) ? s0
->z
: s1
->z
;
172 d
->w
= (s0
->w
< s1
->w
) ? s0
->w
: s1
->w
;
173 VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
174 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
177 void vshader_mov(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
182 VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
183 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
186 void vshader_mul(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
187 d
->x
= s0
->x
* s1
->x
;
188 d
->y
= s0
->y
* s1
->y
;
189 d
->z
= s0
->z
* s1
->z
;
190 d
->w
= s0
->w
* s1
->w
;
191 VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
192 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
195 void vshader_nop(void) {
196 /* NOPPPP ahhh too easy ;) */
197 VSTRACE(("executing nop\n"));
200 void vshader_rcp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
201 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
== s0
->w
) ? HUGE_VAL
: 1.0f
/ s0
->w
;
202 VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
203 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
206 void vshader_rsq(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
207 float tmp_f
= fabsf(s0
->w
);
208 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
== tmp_f
) ? HUGE_VAL
: ((1.0f
!= tmp_f
) ? 1.0f
/ sqrtf(tmp_f
) : 1.0f
);
209 VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
210 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
213 void vshader_sge(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
214 d
->x
= (s0
->x
>= s1
->x
) ? 1.0f
: 0.0f
;
215 d
->y
= (s0
->y
>= s1
->y
) ? 1.0f
: 0.0f
;
216 d
->z
= (s0
->z
>= s1
->z
) ? 1.0f
: 0.0f
;
217 d
->w
= (s0
->w
>= s1
->w
) ? 1.0f
: 0.0f
;
218 VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
219 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
222 void vshader_slt(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
223 d
->x
= (s0
->x
< s1
->x
) ? 1.0f
: 0.0f
;
224 d
->y
= (s0
->y
< s1
->y
) ? 1.0f
: 0.0f
;
225 d
->z
= (s0
->z
< s1
->z
) ? 1.0f
: 0.0f
;
226 d
->w
= (s0
->w
< s1
->w
) ? 1.0f
: 0.0f
;
227 VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
228 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
231 void vshader_sub(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
232 d
->x
= s0
->x
- s1
->x
;
233 d
->y
= s0
->y
- s1
->y
;
234 d
->z
= s0
->z
- s1
->z
;
235 d
->w
= s0
->w
- s1
->w
;
236 VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
237 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
241 * Version 1.1 specific
244 void vshader_exp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
245 d
->x
= d
->y
= d
->z
= d
->w
= powf(2.0f
, s0
->w
);
246 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
247 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
250 void vshader_log(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
251 float tmp_f
= fabsf(s0
->w
);
252 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
!= tmp_f
) ? logf(tmp_f
) / logf(2.0f
) : -HUGE_VAL
;
253 VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
254 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
257 void vshader_frc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
258 d
->x
= s0
->x
- floorf(s0
->x
);
259 d
->y
= s0
->y
- floorf(s0
->y
);
262 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
263 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
266 typedef FLOAT D3DMATRIX44
[4][4];
267 typedef FLOAT D3DMATRIX43
[4][3];
268 typedef FLOAT D3DMATRIX34
[3][4];
269 typedef FLOAT D3DMATRIX33
[3][3];
270 typedef FLOAT D3DMATRIX23
[2][3];
272 void vshader_m4x4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat
) {
274 * Buggy CODE: here only if cast not work for copy/paste
275 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
276 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
277 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
278 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
279 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
280 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
281 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
283 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
+ mat
[0][3] * s0
->w
;
284 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
+ mat
[1][3] * s0
->w
;
285 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
+ mat
[2][3] * s0
->w
;
286 d
->w
= mat
[3][0] * s0
->x
+ mat
[3][1] * s0
->y
+ mat
[3][2] * s0
->z
+ mat
[3][3] * s0
->w
;
287 VSTRACE(("executing m4x4(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat
[0][0], mat
[0][1], mat
[0][2], mat
[0][3], s0
->x
, d
->x
));
288 VSTRACE(("executing m4x4(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], mat
[1][3], s0
->y
, d
->y
));
289 VSTRACE(("executing m4x4(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat
[2][0], mat
[2][1], mat
[2][2], mat
[2][3], s0
->z
, d
->z
));
290 VSTRACE(("executing m4x4(4): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat
[3][0], mat
[3][1], mat
[3][2], mat
[3][3], s0
->w
, d
->w
));
293 void vshader_m4x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX34 mat
) {
294 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
+ mat
[0][3] * s0
->w
;
295 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
+ mat
[1][3] * s0
->w
;
296 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
+ mat
[2][3] * s0
->w
;
298 VSTRACE(("executing m4x3(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat
[0][0], mat
[0][1], mat
[0][2], mat
[0][3], s0
->x
, d
->x
));
299 VSTRACE(("executing m4x3(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], mat
[1][3], s0
->y
, d
->y
));
300 VSTRACE(("executing m4x3(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat
[2][0], mat
[2][1], mat
[2][2], mat
[2][3], s0
->z
, d
->z
));
301 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0
->w
, d
->w
));
304 void vshader_m3x4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX43 mat
) {
305 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
306 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
307 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
;
308 d
->w
= mat
[3][0] * s0
->x
+ mat
[3][1] * s0
->y
+ mat
[3][2] * s0
->z
;
309 VSTRACE(("executing m3x4(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat
[0][0], mat
[0][1], mat
[0][2], s0
->x
, d
->x
));
310 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], s0
->y
, d
->y
));
311 VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat
[2][0], mat
[2][1], mat
[2][2], s0
->z
, d
->z
));
312 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat
[3][0], mat
[3][1], mat
[3][2], s0
->w
, d
->w
));
315 void vshader_m3x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX33 mat
) {
316 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
317 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
318 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
;
320 VSTRACE(("executing m3x3(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat
[0][0], mat
[0][1], mat
[0][2], s0
->x
, d
->x
));
321 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], s0
->y
, d
->y
));
322 VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat
[2][0], mat
[2][1], mat
[2][2], s0
->z
, d
->z
));
323 VSTRACE(("executing m3x3(4): (%f) \n", d
->w
));
326 void vshader_m3x2(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX23 mat
) {
328 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
329 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
335 * Version 2.0 specific
337 void vshader_lrp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
338 d
->x
= s0
->x
* (s1
->x
- s2
->x
) + s2
->x
;
339 d
->y
= s0
->y
* (s1
->y
- s2
->y
) + s2
->y
;
340 d
->z
= s0
->z
* (s1
->z
- s2
->z
) + s2
->z
;
341 d
->w
= s0
->w
* (s1
->w
- s2
->w
) + s2
->w
;
344 void vshader_crs(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
345 d
->x
= s0
->y
* s1
->z
- s0
->z
* s1
->y
;
346 d
->y
= s0
->z
* s1
->x
- s0
->x
* s1
->z
;
347 d
->z
= s0
->x
* s1
->y
- s0
->y
* s1
->x
;
348 d
->w
= 0.9f
; /* w is undefined, so set it to something safeish */
350 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
351 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
354 void vshader_abs(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
360 VSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
361 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
365 void vshader_texcoord(WINED3DSHADERVECTOR
* d
) {
369 void vshader_texkill(WINED3DSHADERVECTOR
* d
) {
373 void vshader_tex(WINED3DSHADERVECTOR
* d
) {
376 void vshader_texld(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
380 void vshader_texbem(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
384 void vshader_texbeml(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
388 void vshader_texreg2ar(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
392 void vshader_texreg2gb(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
396 void vshader_texm3x2pad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
400 void vshader_texm3x2tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
404 void vshader_texm3x3pad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
408 void vshader_texm3x3tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
412 void vshader_texm3x3diff(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
416 void vshader_texm3x3spec(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
420 void vshader_texm3x3vspec(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
424 void vshader_cnd(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
428 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
429 void vshader_def(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
, WINED3DSHADERVECTOR
* s3
) {
433 void vshader_texreg2rgb(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
437 void vshader_texdp3tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
441 void vshader_texm3x2depth(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
445 void vshader_texdp3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
449 void vshader_texm3x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
453 void vshader_texdepth(WINED3DSHADERVECTOR
* d
) {
457 void vshader_cmp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
461 void vshader_bem(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
465 void vshader_call(WINED3DSHADERVECTOR
* d
) {
469 void vshader_callnz(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
473 void vshader_loop(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
477 void vshader_ret(WINED3DSHADERVECTOR
* d
) {
481 void vshader_endloop(WINED3DSHADERVECTOR
* d
) {
485 void vshader_dcl(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
489 void vshader_pow(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
493 void vshader_sng(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
497 void vshader_nrm(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
501 void vshader_sincos(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
505 void vshader_rep(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
509 void vshader_endrep(void) {
513 void vshader_if(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
517 void vshader_ifc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
521 void vshader_else(WINED3DSHADERVECTOR
* d
) {
525 void vshader_label(WINED3DSHADERVECTOR
* d
) {
529 void vshader_endif(WINED3DSHADERVECTOR
* d
) {
533 void vshader_break(WINED3DSHADERVECTOR
* d
) {
537 void vshader_breakc(WINED3DSHADERVECTOR
* d
) {
541 void vshader_mova(WINED3DSHADERVECTOR
* d
) {
545 void vshader_defb(WINED3DSHADERVECTOR
* d
) {
549 void vshader_defi(WINED3DSHADERVECTOR
* d
) {
553 void vshader_dp2add(WINED3DSHADERVECTOR
* d
) {
557 void vshader_dsx(WINED3DSHADERVECTOR
* d
) {
561 void vshader_dsy(WINED3DSHADERVECTOR
* d
) {
565 void vshader_texldd(WINED3DSHADERVECTOR
* d
) {
569 void vshader_setp(WINED3DSHADERVECTOR
* d
) {
573 void vshader_texldl(WINED3DSHADERVECTOR
* d
) {
577 void vshader_breakp(WINED3DSHADERVECTOR
* d
) {
583 * log, exp, frc, m*x* seems to be macros ins ... to see
585 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins
[] = {
586 {D3DSIO_NOP
, "nop", "NOP", 0, vshader_nop
, 0, 0},
587 {D3DSIO_MOV
, "mov", "MOV", 2, vshader_mov
, 0, 0},
588 {D3DSIO_ADD
, "add", "ADD", 3, vshader_add
, 0, 0},
589 {D3DSIO_SUB
, "sub", "SUB", 3, vshader_sub
, 0, 0},
590 {D3DSIO_MAD
, "mad", "MAD", 4, vshader_mad
, 0, 0},
591 {D3DSIO_MUL
, "mul", "MUL", 3, vshader_mul
, 0, 0},
592 {D3DSIO_RCP
, "rcp", "RCP", 2, vshader_rcp
, 0, 0},
593 {D3DSIO_RSQ
, "rsq", "RSQ", 2, vshader_rsq
, 0, 0},
594 {D3DSIO_DP3
, "dp3", "DP3", 3, vshader_dp3
, 0, 0},
595 {D3DSIO_DP4
, "dp4", "DP4", 3, vshader_dp4
, 0, 0},
596 {D3DSIO_MIN
, "min", "MIN", 3, vshader_min
, 0, 0},
597 {D3DSIO_MAX
, "max", "MAX", 3, vshader_max
, 0, 0},
598 {D3DSIO_SLT
, "slt", "SLT", 3, vshader_slt
, 0, 0},
599 {D3DSIO_SGE
, "sge", "SGE", 3, vshader_sge
, 0, 0},
600 {D3DSIO_ABS
, "abs", "ABS", 2, vshader_abs
, 0, 0},
601 {D3DSIO_EXP
, "exp", "EX2", 2, vshader_exp
, 0, 0},
602 {D3DSIO_LOG
, "log", "LG2", 2, vshader_log
, 0, 0},
603 {D3DSIO_LIT
, "lit", "LIT", 2, vshader_lit
, 0, 0},
604 {D3DSIO_DST
, "dst", "DST", 3, vshader_dst
, 0, 0},
605 {D3DSIO_LRP
, "lrp", "LRP", 4, vshader_lrp
, 0, 0},
606 {D3DSIO_FRC
, "frc", "FRC", 2, vshader_frc
, 0, 0},
607 {D3DSIO_M4x4
, "m4x4", "undefined", 3, vshader_m4x4
, 0, 0},
608 {D3DSIO_M4x3
, "m4x3", "undefined", 3, vshader_m4x3
, 0, 0},
609 {D3DSIO_M3x4
, "m3x4", "undefined", 3, vshader_m3x4
, 0, 0},
610 {D3DSIO_M3x3
, "m3x3", "undefined", 3, vshader_m3x3
, 0, 0},
611 {D3DSIO_M3x2
, "m3x2", "undefined", 3, vshader_m3x2
, 0, 0},
612 /** FIXME: use direct access so add the others opcodes as stubs */
613 /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
614 They can be easily managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
615 {D3DSIO_CALL
, "call", GLNAME_REQUIRE_GLSL
, 1, vshader_call
, 0, 0},
616 {D3DSIO_CALLNZ
, "callnz", GLNAME_REQUIRE_GLSL
, 2, vshader_callnz
, 0, 0},
617 {D3DSIO_LOOP
, "loop", GLNAME_REQUIRE_GLSL
, 2, vshader_loop
, 0, 0},
618 {D3DSIO_RET
, "ret", GLNAME_REQUIRE_GLSL
, 0, vshader_ret
, 0, 0},
619 {D3DSIO_ENDLOOP
, "endloop", GLNAME_REQUIRE_GLSL
, 0, vshader_endloop
, 0, 0},
620 {D3DSIO_LABEL
, "label", GLNAME_REQUIRE_GLSL
, 1, vshader_label
, 0, 0},
621 /* DCL is a specil operation */
622 {D3DSIO_DCL
, "dcl", NULL
, 1, vshader_dcl
, 0, 0},
623 {D3DSIO_POW
, "pow", "POW", 3, vshader_pow
, 0, 0},
624 {D3DSIO_CRS
, "crs", "XPS", 3, vshader_crs
, 0, 0},
625 /* TODO: sng can possibly be performed as
628 {D3DSIO_SGN
, "sng", NULL
, 2, vshader_sng
, 0, 0},
629 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
632 MUL vec.xyz, vec, tmp;
633 but I think this is better because it accounts for w properly.
639 {D3DSIO_NRM
, "nrm", NULL
, 2, vshader_nrm
, 0, 0},
640 {D3DSIO_SINCOS
, "sincos", NULL
, 2, vshader_sincos
, 0, 0},
641 {D3DSIO_REP
, "rep", GLNAME_REQUIRE_GLSL
, 2, vshader_rep
, 0, 0},
642 {D3DSIO_ENDREP
, "endrep", GLNAME_REQUIRE_GLSL
, 0, vshader_endrep
, 0, 0},
643 {D3DSIO_IF
, "if", GLNAME_REQUIRE_GLSL
, 2, vshader_if
, 0, 0},
644 {D3DSIO_IFC
, "ifc", GLNAME_REQUIRE_GLSL
, 2, vshader_ifc
, 0, 0},
645 {D3DSIO_ELSE
, "else", GLNAME_REQUIRE_GLSL
, 2, vshader_else
, 0, 0},
646 {D3DSIO_ENDIF
, "endif", GLNAME_REQUIRE_GLSL
, 2, vshader_endif
, 0, 0},
647 {D3DSIO_BREAK
, "break", GLNAME_REQUIRE_GLSL
, 2, vshader_break
, 0, 0},
648 {D3DSIO_BREAKC
, "breakc", GLNAME_REQUIRE_GLSL
, 2, vshader_breakc
, 0, 0},
649 {D3DSIO_MOVA
, "mova", GLNAME_REQUIRE_GLSL
, 2, vshader_mova
, 0, 0},
650 {D3DSIO_DEFB
, "defb", GLNAME_REQUIRE_GLSL
, 2, vshader_defb
, 0, 0},
651 {D3DSIO_DEFI
, "defi", GLNAME_REQUIRE_GLSL
, 2, vshader_defi
, 0, 0},
653 {D3DSIO_TEXCOORD
, "texcoord", GLNAME_REQUIRE_GLSL
, 1, vshader_texcoord
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
654 {D3DSIO_TEXCOORD
, "texcrd", GLNAME_REQUIRE_GLSL
, 2, vshader_texcoord
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
655 {D3DSIO_TEXKILL
, "texkill", GLNAME_REQUIRE_GLSL
, 1, vshader_texkill
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
656 {D3DSIO_TEX
, "tex", GLNAME_REQUIRE_GLSL
, 1, vshader_tex
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
657 {D3DSIO_TEX
, "texld", GLNAME_REQUIRE_GLSL
, 2, vshader_texld
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
658 {D3DSIO_TEXBEM
, "texbem", GLNAME_REQUIRE_GLSL
, 2, vshader_texbem
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
659 {D3DSIO_TEXBEML
, "texbeml", GLNAME_REQUIRE_GLSL
, 2, vshader_texbeml
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
660 {D3DSIO_TEXREG2AR
,"texreg2ar",GLNAME_REQUIRE_GLSL
, 2, vshader_texreg2ar
, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
661 {D3DSIO_TEXREG2GB
,"texreg2gb",GLNAME_REQUIRE_GLSL
, 2, vshader_texreg2gb
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
662 {D3DSIO_TEXM3x2PAD
, "texm3x2pad", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x2pad
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
663 {D3DSIO_TEXM3x2TEX
, "texm3x2tex", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x2tex
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
664 {D3DSIO_TEXM3x3DIFF
, "texm3x3diff", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x3diff
, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
665 {D3DSIO_TEXM3x3SPEC
, "texm3x3spec", GLNAME_REQUIRE_GLSL
, 3, vshader_texm3x3spec
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666 {D3DSIO_TEXM3x3VSPEC
, "texm3x3vspe", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x3vspec
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
668 {D3DSIO_EXPP
, "expp", "EXP", 2, vshader_expp
, 0, 0},
669 {D3DSIO_LOGP
, "logp", "LOG", 2, vshader_logp
, 0, 0},
670 {D3DSIO_CND
, "cnd", GLNAME_REQUIRE_GLSL
, 4, vshader_cnd
, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
671 /* def is a special operation */
672 {D3DSIO_DEF
, "def", NULL
, 5, vshader_def
, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
673 {D3DSIO_TEXREG2RGB
, "texreg2rgb", GLNAME_REQUIRE_GLSL
, 2, vshader_texreg2rgb
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674 {D3DSIO_TEXDP3TEX
, "texdp3tex", GLNAME_REQUIRE_GLSL
, 2, vshader_texdp3tex
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
675 {D3DSIO_TEXM3x2DEPTH
, "texm3x2depth", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x2depth
,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
676 {D3DSIO_TEXDP3
, "texdp3", GLNAME_REQUIRE_GLSL
, 2, vshader_texdp3
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
677 {D3DSIO_TEXM3x3
, "texm3x3", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x3
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
678 {D3DSIO_TEXDEPTH
, "texdepth", GLNAME_REQUIRE_GLSL
,1, vshader_texdepth
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
679 {D3DSIO_CMP
, "cmp", GLNAME_REQUIRE_GLSL
, 4, vshader_cmp
, D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
680 {D3DSIO_BEM
, "bem", GLNAME_REQUIRE_GLSL
, 3, vshader_bem
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
681 /* TODO: dp2add can be made out of multiple instuctions */
682 {D3DSIO_DP2ADD
, "dp2add", GLNAME_REQUIRE_GLSL
, 2, vshader_dp2add
, 0, 0},
683 {D3DSIO_DSX
, "dsx", GLNAME_REQUIRE_GLSL
, 2, vshader_dsx
, 0, 0},
684 {D3DSIO_DSY
, "dsy", GLNAME_REQUIRE_GLSL
, 2, vshader_dsy
, 0, 0},
685 {D3DSIO_TEXLDD
, "texldd", GLNAME_REQUIRE_GLSL
, 2, vshader_texldd
, 0, 0},
686 {D3DSIO_SETP
, "setp", GLNAME_REQUIRE_GLSL
, 2, vshader_setp
, 0, 0},
687 {D3DSIO_TEXLDL
, "texdl", GLNAME_REQUIRE_GLSL
, 2, vshader_texldl
, 0, 0},
688 {D3DSIO_BREAKP
, "breakp", GLNAME_REQUIRE_GLSL
, 2, vshader_breakp
, 0, 0},
689 {D3DSIO_PHASE
, "phase", GLNAME_REQUIRE_GLSL
, 0, vshader_nop
, 0, 0},
690 {0, NULL
, NULL
, 0, NULL
, 0, 0}
694 inline static const SHADER_OPCODE
* vshader_program_get_opcode(IWineD3DVertexShaderImpl
*This
, const DWORD code
) {
696 const SHADER_OPCODE
*shader_ins
= This
->baseShader
.shader_ins
;
698 /** TODO: use dichotomic search or hash table */
699 while (NULL
!= shader_ins
[i
].name
) {
700 if ((code
& D3DSI_OPCODE_MASK
) == shader_ins
[i
].opcode
) {
701 return &shader_ins
[i
];
705 FIXME("Unsupported opcode %lx\n",code
);
709 inline static void vshader_program_dump_param(const DWORD param
, int input
) {
710 static const char* rastout_reg_names
[] = { "oPos", "oFog", "oPts" };
711 static const char swizzle_reg_chars
[] = "xyzw";
713 DWORD reg
= param
& 0x00001FFF;
714 DWORD regtype
= ((param
& D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
);
716 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) TRACE("-");
720 TRACE("R[%lu]", reg
);
726 TRACE("C[%s%lu]", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
728 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
729 TRACE("a[%lu]", reg
);
732 TRACE("%s", rastout_reg_names
[reg
]);
735 TRACE("oD[%lu]", reg
);
737 case D3DSPR_TEXCRDOUT
:
738 TRACE("oT[%lu]", reg
);
741 FIXME("Unknown %lu %u reg %lu\n",regtype
, D3DSPR_ATTROUT
, reg
);
746 /** operand output */
747 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
748 if (param
& D3DSP_WRITEMASK_0
) TRACE(".x");
749 if (param
& D3DSP_WRITEMASK_1
) TRACE(".y");
750 if (param
& D3DSP_WRITEMASK_2
) TRACE(".z");
751 if (param
& D3DSP_WRITEMASK_3
) TRACE(".w");
755 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
756 DWORD swizzle_x
= swizzle
& 0x03;
757 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
758 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
759 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
761 * swizzle bits fields:
764 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) != swizzle
) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
765 if (swizzle_x
== swizzle_y
&&
766 swizzle_x
== swizzle_z
&&
767 swizzle_x
== swizzle_w
) {
768 TRACE(".%c", swizzle_reg_chars
[swizzle_x
]);
771 swizzle_reg_chars
[swizzle_x
],
772 swizzle_reg_chars
[swizzle_y
],
773 swizzle_reg_chars
[swizzle_z
],
774 swizzle_reg_chars
[swizzle_w
]);
780 inline static void vshader_program_dump_vs_param(const DWORD param
, int input
) {
781 static const char* rastout_reg_names
[] = { "oPos", "oFog", "oPts" };
782 static const char swizzle_reg_chars
[] = "xyzw";
783 /* the unknown mask is for bits not yet accounted for by any other mask... */
784 #define UNKNOWN_MASK 0xC000
786 /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
787 #define EXTENDED_REG 0x1800
789 DWORD reg
= param
& D3DSP_REGNUM_MASK
; /* 0x00001FFF; isn't this D3DSP_REGNUM_MASK? */
790 DWORD regtype
= ((param
& D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
) | ((param
& EXTENDED_REG
) >> 8);
792 if(param
& UNKNOWN_MASK
) { /* if this register has any of the unknown bits set then report them*/
793 FIXME("Unknown bits set regtype %lx , %lx, UK(%lx)\n", regtype
, (param
& EXTENDED_REG
), param
& UNKNOWN_MASK
);
796 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) TRACE("-");
798 switch (regtype
/*<< D3DSP_REGTYPE_SHIFT*/) {
806 TRACE("c%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
808 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
812 TRACE("%s", rastout_reg_names
[reg
]);
817 case D3DSPR_TEXCRDOUT
:
820 case D3DSPR_CONSTINT
:
821 TRACE("i%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
823 case D3DSPR_CONSTBOOL
:
824 TRACE("b%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
830 TRACE("aL%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
833 FIXME("Unknown %lu reg %lu\n",regtype
, reg
);
838 /** operand output */
839 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
840 if (param
& D3DSP_WRITEMASK_0
) TRACE(".x");
841 if (param
& D3DSP_WRITEMASK_1
) TRACE(".y");
842 if (param
& D3DSP_WRITEMASK_2
) TRACE(".z");
843 if (param
& D3DSP_WRITEMASK_3
) TRACE(".w");
847 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
848 DWORD swizzle_x
= swizzle
& 0x03;
849 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
850 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
851 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
853 * swizzle bits fields:
856 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) != swizzle
) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
857 if (swizzle_x
== swizzle_y
&&
858 swizzle_x
== swizzle_z
&&
859 swizzle_x
== swizzle_w
) {
860 TRACE(".%c", swizzle_reg_chars
[swizzle_x
]);
863 swizzle_reg_chars
[swizzle_x
],
864 swizzle_reg_chars
[swizzle_y
],
865 swizzle_reg_chars
[swizzle_z
],
866 swizzle_reg_chars
[swizzle_w
]);
872 inline static void vshader_program_dump_decl_usage(IWineD3DVertexShaderImpl
*This
, DWORD token
) {
874 switch(token
& 0xFFFF) {
875 case D3DDECLUSAGE_POSITION
:
876 TRACE("%s%ld ", "position",(token
& 0xF0000) >> 16);
878 case D3DDECLUSAGE_BLENDINDICES
:
879 TRACE("%s ", "blend");
881 case D3DDECLUSAGE_BLENDWEIGHT
:
882 TRACE("%s ", "weight");
884 case D3DDECLUSAGE_NORMAL
:
885 TRACE("%s%ld ", "normal",(token
& 0xF0000) >> 16);
887 case D3DDECLUSAGE_PSIZE
:
888 TRACE("%s ", "psize");
890 case D3DDECLUSAGE_COLOR
:
891 if((token
& 0xF0000) >> 16 == 0) {
892 TRACE("%s ", "color");
894 TRACE("%s ", "specular");
897 case D3DDECLUSAGE_TEXCOORD
:
898 TRACE("%s%ld ", "texture", (token
& 0xF0000) >> 16);
900 case D3DDECLUSAGE_TANGENT
:
901 TRACE("%s ", "tangent");
903 case D3DDECLUSAGE_BINORMAL
:
904 TRACE("%s ", "binormal");
906 case D3DDECLUSAGE_TESSFACTOR
:
907 TRACE("%s ", "tessfactor");
909 case D3DDECLUSAGE_POSITIONT
:
910 TRACE("%s%ld ", "positionT",(token
& 0xF0000) >> 16);
912 case D3DDECLUSAGE_FOG
:
915 case D3DDECLUSAGE_DEPTH
:
916 TRACE("%s ", "depth");
918 case D3DDECLUSAGE_SAMPLE
:
919 TRACE("%s ", "sample");
922 FIXME("Unrecognised dcl %08lx", token
& 0xFFFF);
926 inline static BOOL
vshader_is_version_token(DWORD token
) {
927 return 0xFFFE0000 == (token
& 0xFFFE0000);
930 inline static BOOL
vshader_is_comment_token(DWORD token
) {
931 return D3DSIO_COMMENT
== (token
& D3DSI_OPCODE_MASK
);
934 inline static void vshader_program_add_output_param_swizzle(const DWORD param
, int is_color
, char *hwLine
) {
935 /** operand output */
936 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
938 if (param
& D3DSP_WRITEMASK_0
) { strcat(hwLine
, "x"); }
939 if (param
& D3DSP_WRITEMASK_1
) { strcat(hwLine
, "y"); }
940 if (param
& D3DSP_WRITEMASK_2
) { strcat(hwLine
, "z"); }
941 if (param
& D3DSP_WRITEMASK_3
) { strcat(hwLine
, "w"); }
945 inline static void vshader_program_add_input_param_swizzle(const DWORD param
, int is_color
, char *hwLine
) {
946 static const char swizzle_reg_chars_color_fix
[] = "zyxw";
947 static const char swizzle_reg_chars
[] = "xyzw";
948 const char* swizzle_regs
= NULL
;
952 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
953 DWORD swizzle_x
= swizzle
& 0x03;
954 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
955 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
956 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
959 swizzle_regs
= swizzle_reg_chars_color_fix
;
961 swizzle_regs
= swizzle_reg_chars
;
965 * swizzle bits fields:
968 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) == swizzle
) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
970 sprintf(tmpReg
, ".%c%c%c%c",
971 swizzle_regs
[swizzle_x
],
972 swizzle_regs
[swizzle_y
],
973 swizzle_regs
[swizzle_z
],
974 swizzle_regs
[swizzle_w
]);
975 strcat(hwLine
, tmpReg
);
979 if (swizzle_x
== swizzle_y
&&
980 swizzle_x
== swizzle_z
&&
981 swizzle_x
== swizzle_w
)
983 sprintf(tmpReg
, ".%c", swizzle_regs
[swizzle_x
]);
984 strcat(hwLine
, tmpReg
);
986 sprintf(tmpReg
, ".%c%c%c%c",
987 swizzle_regs
[swizzle_x
],
988 swizzle_regs
[swizzle_y
],
989 swizzle_regs
[swizzle_z
],
990 swizzle_regs
[swizzle_w
]);
991 strcat(hwLine
, tmpReg
);
995 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl
*This
, const DWORD param
, BOOL is_input
, char *hwLine
) {
996 /* oPos, oFog and oPts in D3D */
997 static const char* hwrastout_reg_names
[] = { "result.position", "result.fogcoord", "result.pointsize" };
999 DWORD reg
= param
& 0x00001FFF;
1000 DWORD regtype
= ((param
& D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
);
1002 BOOL is_color
= FALSE
;
1004 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) {
1005 strcat(hwLine
, " -");
1007 strcat(hwLine
, " ");
1012 sprintf(tmpReg
, "T%lu", reg
);
1013 strcat(hwLine
, tmpReg
);
1016 if (reg
== This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DIFFUSE
]
1017 || reg
== This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SPECULAR
]) {
1020 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
1021 if (This
->namedArrays
) {
1022 sprintf(tmpReg
, "namedVertex%lu", reg
);
1024 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
1025 sprintf(tmpReg
, "vertex.attrib[%lu]", reg
);
1027 strcat(hwLine
, tmpReg
);
1030 /* FIXME: some constants are named so we need a constants map*/
1031 if (This
->constantsUsedBitmap
[reg
] == VS_CONSTANT_CONSTANT
) {
1032 if (param
& D3DVS_ADDRMODE_RELATIVE
) {
1033 FIXME("Relative addressing not expected for a named constant %lu\n", reg
);
1035 sprintf(tmpReg
, "const%lu", reg
);
1037 sprintf(tmpReg
, "C[%s%lu]", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "A0.x + " : "", reg
);
1039 strcat(hwLine
, tmpReg
);
1041 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
1042 sprintf(tmpReg
, "A%lu", reg
);
1043 strcat(hwLine
, tmpReg
);
1045 case D3DSPR_RASTOUT
:
1046 sprintf(tmpReg
, "%s", hwrastout_reg_names
[reg
]);
1047 strcat(hwLine
, tmpReg
);
1049 case D3DSPR_ATTROUT
:
1051 strcat(hwLine
, "result.color.primary");
1053 strcat(hwLine
, "result.color.secondary");
1056 case D3DSPR_TEXCRDOUT
:
1057 sprintf(tmpReg
, "result.texcoord[%lu]", reg
);
1058 strcat(hwLine
, tmpReg
);
1061 FIXME("Unknown reg type %ld %ld\n", regtype
, reg
);
1066 vshader_program_add_output_param_swizzle(param
, is_color
, hwLine
);
1068 vshader_program_add_input_param_swizzle(param
, is_color
, hwLine
);
1072 DWORD MacroExpansion
[4*4];
1074 int ExpandMxMacro(DWORD macro_opcode
, const DWORD
* args
) {
1076 int nComponents
= 0;
1078 switch(macro_opcode
) {
1081 opcode
= D3DSIO_DP4
;
1085 opcode
= D3DSIO_DP4
;
1089 opcode
= D3DSIO_DP3
;
1093 opcode
= D3DSIO_DP3
;
1097 opcode
= D3DSIO_DP3
;
1102 for (i
= 0; i
< nComponents
; i
++) {
1103 MacroExpansion
[i
*4+0] = opcode
;
1104 MacroExpansion
[i
*4+1] = ((*args
) & ~D3DSP_WRITEMASK_ALL
)|(D3DSP_WRITEMASK_0
<<i
);
1105 MacroExpansion
[i
*4+2] = *(args
+1);
1106 MacroExpansion
[i
*4+3] = (*(args
+2))+i
;
1111 static void parse_decl_usage(IWineD3DVertexShaderImpl
*This
, INT usage
, INT arrayNo
)
1113 switch(usage
& 0xFFFF) {
1114 case D3DDECLUSAGE_POSITION
:
1115 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
1116 TRACE("Setting position to %d\n", arrayNo
);
1117 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITION
] = arrayNo
;
1118 This
->namedArrays
= TRUE
;
1120 /* TODO: position indexes go from 0-8!!*/
1121 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
1122 /* robots uses positions up to 8, the position arrays are just packed.*/
1123 if ((usage
& 0xF0000) >> 16 > 1) {
1124 TRACE("Loaded for position %d (greater than 2)\n", (usage
& 0xF0000) >> 16);
1126 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITION2
+ ((usage
& 0xF0000) >> 16) -1] = arrayNo
;
1127 This
->declaredArrays
= TRUE
;
1130 case D3DDECLUSAGE_BLENDINDICES
:
1131 /* not supported by openGL */
1132 TRACE("Setting BLENDINDICES to %d\n", arrayNo
);
1133 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BLENDINDICES
] = arrayNo
;
1134 This
->declaredArrays
= TRUE
;
1135 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1137 case D3DDECLUSAGE_BLENDWEIGHT
:
1138 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo
);
1139 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BLENDWEIGHT
] = arrayNo
;
1140 This
->namedArrays
= TRUE
;
1141 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1143 case D3DDECLUSAGE_NORMAL
:
1144 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
1145 TRACE("Setting normal to %d\n", arrayNo
);
1146 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_NORMAL
] = arrayNo
;
1147 This
->namedArrays
= TRUE
;
1149 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
1150 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_NORMAL2
] = arrayNo
;
1151 This
->declaredArrays
= TRUE
;
1154 case D3DDECLUSAGE_PSIZE
:
1155 TRACE("Setting PSIZE to %d\n", arrayNo
);
1156 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_PSIZE
] = arrayNo
;
1157 This
->namedArrays
= TRUE
;
1158 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1160 case D3DDECLUSAGE_COLOR
:
1161 if((usage
& 0xF0000) >> 16 == 0) {
1162 TRACE("Setting DIFFUSE to %d\n", arrayNo
);
1163 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DIFFUSE
] = arrayNo
;
1164 This
->namedArrays
= TRUE
;
1166 TRACE("Setting SPECULAR to %d\n", arrayNo
);
1167 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SPECULAR
] = arrayNo
;
1168 This
->namedArrays
= TRUE
;
1171 case D3DDECLUSAGE_TEXCOORD
:
1172 This
->namedArrays
= TRUE
;
1173 /* only 7 texture coords have been designed for, so run a quick sanity check */
1174 if ((usage
& 0xF0000) >> 16 > 7) {
1175 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This
, (usage
& 0xF0000) >> 16);
1177 TRACE("Setting TEXCOORD %d to %d\n", ((usage
& 0xF0000) >> 16), arrayNo
);
1178 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TEXCOORD0
+ ((usage
& 0xF0000) >> 16)] = arrayNo
;
1181 /* The following aren't supported by openGL,
1182 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1183 this should be caught in the first pass */
1184 case D3DDECLUSAGE_TANGENT
:
1185 TRACE("Setting TANGENT to %d\n", arrayNo
);
1186 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TANGENT
] = arrayNo
;
1187 This
->declaredArrays
= TRUE
;
1189 case D3DDECLUSAGE_BINORMAL
:
1190 TRACE("Setting BINORMAL to %d\n", arrayNo
);
1191 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BINORMAL
] = arrayNo
;
1192 This
->declaredArrays
= TRUE
;
1194 case D3DDECLUSAGE_TESSFACTOR
:
1195 TRACE("Setting TESSFACTOR to %d\n", arrayNo
);
1196 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TESSFACTOR
] = arrayNo
;
1197 This
->declaredArrays
= TRUE
;
1199 case D3DDECLUSAGE_POSITIONT
:
1200 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
1201 FIXME("Setting positiont to %d\n", arrayNo
);
1202 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITIONT
] = arrayNo
;
1203 This
->namedArrays
= TRUE
;
1205 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
1206 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITIONT2
] = arrayNo
;
1207 This
->declaredArrays
= TRUE
;
1208 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1211 case D3DDECLUSAGE_FOG
:
1212 /* supported by OpenGL */
1213 TRACE("Setting FOG to %d\n", arrayNo
);
1214 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_FOG
] = arrayNo
;
1215 This
->namedArrays
= TRUE
;
1217 case D3DDECLUSAGE_DEPTH
:
1218 TRACE("Setting DEPTH to %d\n", arrayNo
);
1219 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DEPTH
] = arrayNo
;
1220 This
->declaredArrays
= TRUE
;
1222 case D3DDECLUSAGE_SAMPLE
:
1223 TRACE("Setting SAMPLE to %d\n", arrayNo
);
1224 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SAMPLE
] = arrayNo
;
1225 This
->declaredArrays
= TRUE
;
1228 FIXME("Unrecognised dcl %08x", usage
& 0xFFFF);
1233 * Function parser ...
1236 inline static VOID
IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader
*iface
, CONST DWORD
* pFunction
) {
1237 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1238 const DWORD
* pToken
= pFunction
;
1239 const DWORD
* pSavedToken
= NULL
;
1240 const SHADER_OPCODE
* curOpcode
= NULL
;
1243 unsigned lineNum
= 0;
1244 char *pgmStr
= NULL
;
1246 DWORD nUseAddressRegister
= 0;
1247 DWORD nUseTempRegister
= 0;
1251 #if 0 /* TODO: loope register (just another address register ) */
1252 BOOL hasLoops
= FALSE
;
1255 #define PGMSIZE 65535
1256 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1259 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1260 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1261 if (This
->device
->fixupVertexBufferSize
< PGMSIZE
) {
1262 HeapFree(GetProcessHeap(), 0, This
->fixupVertexBuffer
);
1263 This
->fixupVertexBuffer
= HeapAlloc(GetProcessHeap() , 0, PGMSIZE
);
1264 This
->fixupVertexBufferSize
= PGMSIZE
;
1265 This
->fixupVertexBuffer
[0] = 0;
1267 pgmStr
= This
->device
->fixupVertexBuffer
;
1269 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1270 int _tmpLineLen = strlen(_tmpLine); \
1271 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1272 ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, _tmpLineLen + pgmLength); \
1274 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1276 pgmLength += _tmpLineLen; \
1279 pgmStr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 65535); /* 64kb should be enough */
1280 /* Initialise the shader */
1281 This
->namedArrays
= FALSE
;
1282 This
->declaredArrays
= FALSE
;
1283 for (i
= 0; i
< WINED3DSHADERDECLUSAGE_MAX_USAGE
; i
++) {
1284 This
->arrayUsageMap
[i
] = -1;
1286 /* set all the tmpsUsed to not used */
1287 memset(tmpsUsed
, FALSE
, sizeof(tmpsUsed
));
1289 /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
1290 This
->highestConstant
= -1;
1293 * First pass to determine what we need to declare:
1294 * - Temporary variables
1295 * - Address variables
1297 if (NULL
!= pToken
) {
1298 while (D3DVS_END() != *pToken
) {
1299 if (vshader_is_version_token(*pToken
)) {
1304 if (vshader_is_comment_token(*pToken
)) { /** comment */
1305 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1307 pToken
+= comment_len
;
1310 curOpcode
= vshader_program_get_opcode(This
, *pToken
);
1315 if (NULL
== curOpcode
) {
1316 while (*pToken
& 0x80000000) {
1317 FIXME("unrecognized opcode: %08lx\n", *pToken
);
1318 /* skip unrecognized opcode */
1322 if (curOpcode
->opcode
== D3DSIO_DCL
){
1323 INT usage
= *pToken
++;
1324 INT arrayNo
= (*pToken
++ & 0x00001FFF);
1325 parse_decl_usage(This
, usage
, arrayNo
);
1326 } else if(curOpcode
->opcode
== D3DSIO_DEF
) {
1327 This
->constantsUsedBitmap
[*pToken
& 0xFF] = VS_CONSTANT_CONSTANT
;
1328 FIXME("Constant %ld\n", *pToken
& 0xFF);
1336 /* Check to see if and tmp or addressing redisters are used */
1337 if (curOpcode
->num_params
> 0) {
1338 regtype
= ((((*pToken
) & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
));
1339 reg
= ((*pToken
) & 0x00001FFF);
1340 if (D3DSPR_ADDR
== regtype
&& nUseAddressRegister
<= reg
) nUseAddressRegister
= reg
+ 1;
1341 if (D3DSPR_TEMP
== regtype
){
1342 tmpsUsed
[reg
] = TRUE
;
1343 if(nUseTempRegister
<= reg
) nUseTempRegister
= reg
+ 1;
1346 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
1347 regtype
= ((((*pToken
) & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
));
1348 reg
= ((*pToken
) & 0x00001FFF);
1349 if (D3DSPR_ADDR
== regtype
&& nUseAddressRegister
<= reg
) nUseAddressRegister
= reg
+ 1;
1350 if (D3DSPR_TEMP
== regtype
){
1351 tmpsUsed
[reg
] = TRUE
;
1352 if(nUseTempRegister
<= reg
) nUseTempRegister
= reg
+ 1;
1358 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1359 if (curOpcode
->glname
== GLNAME_REQUIRE_GLSL
) {
1360 FIXME("This shader requires gl shader language support\n");
1362 This
->shaderLanguage
= GLSHADER_GLSL
;
1370 #define VSHADER_ALWAYS_NUMBERED
1373 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1374 /* TODO: using numbered arrays for software shaders makes things easier */
1375 This
->declaredArrays
= TRUE
;
1378 /* named arrays and declared arrays are mutually exclusive */
1379 if (This
->declaredArrays
) {
1380 This
->namedArrays
= FALSE
;
1383 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1384 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1387 /** second pass, now generate */
1390 if (NULL
!= pToken
) {
1393 if ((nRemInstr
>= 0) && (--nRemInstr
== -1))
1394 /* Macro is finished, continue normal path */
1395 pToken
= pSavedToken
;
1396 if (D3DVS_END() == *pToken
)
1399 if (vshader_is_version_token(*pToken
)) { /** version */
1400 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1401 int version
= (((*pToken
>> 8) & 0x0F) * 10) + (*pToken
& 0x0F);
1405 TRACE("found version token vs.%lu.%lu;\n", (*pToken
>> 8) & 0x0F, (*pToken
& 0x0F));
1407 /* Each release of vertex shaders has had different numbers of temp registers */
1410 case 11: numTemps
=12;
1411 numConstants
=96;/* min(GL_LIMITS(constants),96) */
1412 strcpy(tmpLine
, "!!ARBvp1.0\n");
1413 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1415 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1416 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1417 TODO: only map the maximum possible number of constants supported by openGL and not the maximum required by d3d (even better only map the used constants)*/
1418 case 20: numTemps
=12; /* min(GL_LIMITS(temps),12) */
1419 numConstants
=96; /* min(GL_LIMITS(constants),256) */
1420 strcpy(tmpLine
, "!!ARBvp1.0\n");
1421 FIXME("No work done yet to support vs2.0 in hw\n");
1422 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1424 case 21: numTemps
=12; /* min(GL_LIMITS(temps),12) */
1425 numConstants
=96; /* min(GL_LIMITS(constants),256) */
1426 strcpy(tmpLine
, "!!ARBvp1.0\n");
1427 FIXME("No work done yet to support vs2.1 in hw\n");
1428 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1430 case 30: numTemps
=32; /* min(GL_LIMITS(temps),32) */
1431 numConstants
=96;/* min(GL_LIMITS(constants),256) */
1432 strcpy(tmpLine
, "!!ARBvp3.0\n");
1433 FIXME("No work done yet to support vs3.0 in hw\n");
1434 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1437 numTemps
=12;/* min(GL_LIMITS(temps),12) */
1438 numConstants
=96;/* min(GL_LIMITS(constants),96) */
1439 strcpy(tmpLine
, "!!ARBvp1.0\n");
1440 FIXME("Unrecognized vertex shader version %d!\n", version
);
1442 PNSTRCAT(pgmStr
, tmpLine
);
1446 /* This should be a bitmap so that only temp registers that are used are declared. */
1447 for (i
= 0; i
< nUseTempRegister
/* we should check numTemps here */ ; i
++) {
1448 if (tmpsUsed
[i
]) { /* only write out the temps if they are actually in use */
1449 sprintf(tmpLine
, "TEMP T%ld;\n", i
);
1451 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1452 PNSTRCAT(pgmStr
, tmpLine
);
1456 /* TODO: loop register counts as an address register */
1457 for (i
= 0; i
< nUseAddressRegister
; i
++) {
1458 sprintf(tmpLine
, "ADDRESS A%ld;\n", i
);
1460 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1461 PNSTRCAT(pgmStr
, tmpLine
);
1464 /* Due to the dynamic constants binding mechanism, we need to declare
1465 * all the constants for relative addressing. */
1466 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1467 if (GL_VEND(MESA
) || GL_VEND(WINE
)) {
1470 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1471 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1473 sprintf(tmpLine
, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants
, numConstants
- 1);
1474 TRACE("GL HW (%u,%u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1475 PNSTRCAT(pgmStr
, tmpLine
);
1482 if (vshader_is_comment_token(*pToken
)) { /** comment */
1483 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1485 FIXME("#%s\n", (char*)pToken
);
1486 pToken
+= comment_len
;
1490 curOpcode
= vshader_program_get_opcode(This
, *pToken
);
1492 if (NULL
== curOpcode
) {
1493 /* unknown current opcode ... (shouldn't be any!) */
1494 while (*pToken
& 0x80000000) {
1495 FIXME("unrecognized opcode: %08lx\n", *pToken
);
1498 } else if (GLNAME_REQUIRE_GLSL
== curOpcode
->glname
) {
1499 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1501 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode
->name
);
1502 pToken
+= curOpcode
->num_params
;
1504 /* Build opcode for GL vertex_program */
1505 switch (curOpcode
->opcode
) {
1509 /* Address registers must be loaded with the ARL instruction */
1510 if ((((*pToken
) & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
) == D3DSPR_ADDR
) {
1511 if (((*pToken
) & 0x00001FFF) < nUseAddressRegister
) {
1512 strcpy(tmpLine
, "ARL");
1515 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This
, ((*pToken
) & 0x00001FFF));
1537 strcpy(tmpLine
, curOpcode
->glname
);
1544 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1545 nRemInstr
= ExpandMxMacro(curOpcode
->opcode
, pToken
);
1546 /* Save point to next instruction */
1547 pSavedToken
= pToken
+ 3;
1548 /* Execute expanded macro */
1549 pToken
= MacroExpansion
;
1551 /* dcl and def are handeled in the first pass */
1553 if (This
->namedArrays
) {
1554 const char* attribName
= "undefined";
1555 switch(*pToken
& 0xFFFF) {
1556 case D3DDECLUSAGE_POSITION
:
1557 attribName
= "vertex.position";
1559 case D3DDECLUSAGE_BLENDINDICES
:
1560 /* not supported by openGL */
1561 attribName
= "vertex.blend";
1563 case D3DDECLUSAGE_BLENDWEIGHT
:
1564 attribName
= "vertex.weight";
1566 case D3DDECLUSAGE_NORMAL
:
1567 attribName
= "vertex.normal";
1569 case D3DDECLUSAGE_PSIZE
:
1570 attribName
= "vertex.psize";
1572 case D3DDECLUSAGE_COLOR
:
1573 if((*pToken
& 0xF0000) >> 16 == 0) {
1574 attribName
= "vertex.color";
1576 attribName
= "vertex.color.secondary";
1579 case D3DDECLUSAGE_TEXCOORD
:
1583 sprintf(tmpChar
,"vertex.texcoord[%lu]",(*pToken
& 0xF0000) >> 16);
1584 attribName
= tmpChar
;
1587 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1588 case D3DDECLUSAGE_TANGENT
:
1589 attribName
= "vertex.tangent";
1591 case D3DDECLUSAGE_BINORMAL
:
1592 attribName
= "vertex.binormal";
1594 case D3DDECLUSAGE_TESSFACTOR
:
1595 attribName
= "vertex.tessfactor";
1597 case D3DDECLUSAGE_POSITIONT
:
1598 attribName
= "vertex.possitionT";
1600 case D3DDECLUSAGE_FOG
:
1601 attribName
= "vertex.fogcoord";
1603 case D3DDECLUSAGE_DEPTH
:
1604 attribName
= "vertex.depth";
1606 case D3DDECLUSAGE_SAMPLE
:
1607 attribName
= "vertex.sample";
1610 FIXME("Unrecognised dcl %08lx", *pToken
& 0xFFFF);
1615 sprintf(tmpLine
, "ATTRIB ");
1616 vshader_program_add_param(This
, *pToken
, FALSE
, tmpLine
);
1617 sprintf(tmpChar
," = %s", attribName
);
1618 strcat(tmpLine
, tmpChar
);
1619 strcat(tmpLine
,";\n");
1621 if (This
->namedArrays
) {
1622 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
);
1623 PNSTRCAT(pgmStr
, tmpLine
);
1626 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
);
1630 /* eat the token so it doesn't generate a warning */
1638 sprintf(tmpLine
, "PARAM const%lu = {", *pToken
& 0xFF);
1640 sprintf(tmpChar
,"%f ,", *(float *)pToken
);
1641 strcat(tmpLine
, tmpChar
);
1643 sprintf(tmpChar
,"%f ,", *(float *)pToken
);
1644 strcat(tmpLine
, tmpChar
);
1646 sprintf(tmpChar
,"%f ,", *(float *)pToken
);
1647 strcat(tmpLine
, tmpChar
);
1649 sprintf(tmpChar
,"%f}", *(float *)pToken
);
1650 strcat(tmpLine
, tmpChar
);
1652 strcat(tmpLine
,";\n");
1654 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1655 PNSTRCAT(pgmStr
, tmpLine
);
1661 if (curOpcode
->glname
== GLNAME_REQUIRE_GLSL
) {
1662 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode
->name
);
1664 FIXME("Can't handle opcode %s in hwShader\n", curOpcode
->name
);
1667 if (curOpcode
->num_params
> 0) {
1668 vshader_program_add_param(This
, *pToken
, FALSE
, tmpLine
);
1671 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
1672 strcat(tmpLine
, ",");
1673 vshader_program_add_param(This
, *pToken
, TRUE
, tmpLine
);
1677 strcat(tmpLine
,";\n");
1679 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1680 PNSTRCAT(pgmStr
, tmpLine
);
1684 strcpy(tmpLine
, "END\n");
1686 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1687 PNSTRCAT(pgmStr
, tmpLine
);
1690 /* finally null terminate the pgmStr*/
1691 pgmStr
[pgmLength
] = 0;
1693 /* Check that Vertex Shaders are supported */
1694 if (GL_SUPPORT(ARB_VERTEX_PROGRAM
)) {
1695 /* Create the hw shader */
1696 /* TODO: change to resource.glObjectHandel or something like that */
1697 GL_EXTCALL(glGenProgramsARB(1, &This
->baseShader
.prgId
));
1698 TRACE("Creating a hw vertex shader, prg=%d\n", This
->baseShader
.prgId
);
1699 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, This
->baseShader
.prgId
));
1701 /* Create the program and check for errors */
1702 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
, strlen(pgmStr
)/*pgmLength*/, pgmStr
));
1703 if (glGetError() == GL_INVALID_OPERATION
) {
1705 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB
, &errPos
);
1706 FIXME("HW VertexShader Error at position %d: %s\n",
1707 errPos
, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB
)));
1708 This
->baseShader
.prgId
= -1;
1711 #if 1 /* if were using the data buffer of device then we don't need to free it */
1712 HeapFree(GetProcessHeap(), 0, pgmStr
);
1717 BOOL
IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader
* iface
, WINEVSHADERINPUTDATA
* input
, WINEVSHADEROUTPUTDATA
* output
) {
1719 * TODO: use the NV_vertex_program (or 1_1) extension
1720 * and specifics vendors (ARB_vertex_program??) variants for it
1725 HRESULT WINAPI
IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader
* iface
, WINEVSHADERINPUTDATA
* input
, WINEVSHADEROUTPUTDATA
* output
) {
1726 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1728 /** Vertex Shader Temporary Registers */
1729 WINED3DSHADERVECTOR R
[12];
1730 /*D3DSHADERSCALAR A0;*/
1731 WINED3DSHADERVECTOR A
[1];
1732 /** temporary Vector for modifier management */
1733 WINED3DSHADERVECTOR d
;
1734 WINED3DSHADERVECTOR s
[3];
1736 const DWORD
* pToken
= This
->baseShader
.function
;
1737 const SHADER_OPCODE
* curOpcode
= NULL
;
1738 /** functions parameters */
1739 WINED3DSHADERVECTOR
* p
[4];
1740 WINED3DSHADERVECTOR
* p_send
[4];
1743 /** init temporary register */
1744 memset(R
, 0, 12 * sizeof(WINED3DSHADERVECTOR
));
1746 /* vshader_program_parse(vshader); */
1747 #if 0 /* Must not be 1 in cvs */
1749 TRACE_VSVECTOR(This
->data
->C
[0]);
1750 TRACE_VSVECTOR(This
->data
->C
[1]);
1751 TRACE_VSVECTOR(This
->data
->C
[2]);
1752 TRACE_VSVECTOR(This
->data
->C
[3]);
1753 TRACE_VSVECTOR(This
->data
->C
[4]);
1754 TRACE_VSVECTOR(This
->data
->C
[5]);
1755 TRACE_VSVECTOR(This
->data
->C
[6]);
1756 TRACE_VSVECTOR(This
->data
->C
[7]);
1757 TRACE_VSVECTOR(This
->data
->C
[8]);
1758 TRACE_VSVECTOR(This
->data
->C
[64]);
1759 TRACE_VSVECTOR(input
->V
[D3DVSDE_POSITION
]);
1760 TRACE_VSVECTOR(input
->V
[D3DVSDE_BLENDWEIGHT
]);
1761 TRACE_VSVECTOR(input
->V
[D3DVSDE_BLENDINDICES
]);
1762 TRACE_VSVECTOR(input
->V
[D3DVSDE_NORMAL
]);
1763 TRACE_VSVECTOR(input
->V
[D3DVSDE_PSIZE
]);
1764 TRACE_VSVECTOR(input
->V
[D3DVSDE_DIFFUSE
]);
1765 TRACE_VSVECTOR(input
->V
[D3DVSDE_SPECULAR
]);
1766 TRACE_VSVECTOR(input
->V
[D3DVSDE_TEXCOORD0
]);
1767 TRACE_VSVECTOR(input
->V
[D3DVSDE_TEXCOORD1
]);
1770 TRACE_VSVECTOR(vshader
->data
->C
[64]);
1771 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1773 /* the first dword is the version tag */
1774 /* TODO: parse it */
1776 if (vshader_is_version_token(*pToken
)) { /** version */
1779 while (D3DVS_END() != *pToken
) {
1780 if (vshader_is_comment_token(*pToken
)) { /** comment */
1781 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1783 pToken
+= comment_len
;
1786 curOpcode
= vshader_program_get_opcode(This
, *pToken
);
1788 if (NULL
== curOpcode
) {
1790 /* unknown current opcode ... */
1791 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1792 while (*pToken
& 0x80000000) {
1794 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken
- 1) - This
->baseShader
.function
, *(pToken
- 1));
1796 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken
- This
->baseShader
.function
, *pToken
);
1797 vshader_program_dump_param(*pToken
, i
);
1804 if (curOpcode
->num_params
> 0) {
1805 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1806 for (i
= 0; i
< curOpcode
->num_params
; ++i
) {
1807 DWORD reg
= pToken
[i
] & 0x00001FFF;
1808 DWORD regtype
= ((pToken
[i
] & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
);
1810 switch (regtype
<< D3DSP_REGTYPE_SHIFT
) {
1812 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1816 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1817 p
[i
] = &input
->V
[reg
];
1820 if (pToken
[i
] & D3DVS_ADDRMODE_RELATIVE
) {
1821 p
[i
] = &This
->data
->C
[(DWORD
) A
[0].x
+ reg
];
1823 p
[i
] = &This
->data
->C
[reg
];
1826 case D3DSPR_ADDR
: /* case D3DSPR_TEXTURE: */
1828 ERR("cannot handle address registers != a0, forcing use of a0\n");
1831 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1834 case D3DSPR_RASTOUT
:
1836 case D3DSRO_POSITION
:
1837 p
[i
] = &output
->oPos
;
1840 p
[i
] = &output
->oFog
;
1842 case D3DSRO_POINT_SIZE
:
1843 p
[i
] = &output
->oPts
;
1847 case D3DSPR_ATTROUT
:
1848 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1849 p
[i
] = &output
->oD
[reg
];
1851 case D3DSPR_TEXCRDOUT
:
1852 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1853 p
[i
] = &output
->oT
[reg
];
1855 /* TODO Decls and defs */
1864 if (i
> 0) { /* input reg */
1865 DWORD swizzle
= (pToken
[i
] & D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
1866 UINT isNegative
= ((pToken
[i
] & D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
);
1868 if (!isNegative
&& (D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) == swizzle
) {
1869 /* TRACE("p[%d] not swizzled\n", i); */
1872 DWORD swizzle_x
= swizzle
& 0x03;
1873 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
1874 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
1875 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
1876 /* TRACE("p[%d] swizzled\n", i); */
1877 float* tt
= (float*) p
[i
];
1878 s
[i
].x
= (isNegative
) ? -tt
[swizzle_x
] : tt
[swizzle_x
];
1879 s
[i
].y
= (isNegative
) ? -tt
[swizzle_y
] : tt
[swizzle_y
];
1880 s
[i
].z
= (isNegative
) ? -tt
[swizzle_z
] : tt
[swizzle_z
];
1881 s
[i
].w
= (isNegative
) ? -tt
[swizzle_w
] : tt
[swizzle_w
];
1884 } else { /* output reg */
1885 if ((pToken
[i
] & D3DSP_WRITEMASK_ALL
) == D3DSP_WRITEMASK_ALL
) {
1888 p_send
[i
] = &d
; /* to be post-processed for modifiers management */
1894 switch (curOpcode
->num_params
) {
1896 curOpcode
->soft_fct();
1899 curOpcode
->soft_fct(p_send
[0]);
1902 curOpcode
->soft_fct(p_send
[0], p_send
[1]);
1905 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2]);
1908 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3]);
1911 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3], p_send
[4]);
1914 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3], p_send
[4], p_send
[5]);
1917 ERR("%s too many params: %u\n", curOpcode
->name
, curOpcode
->num_params
);
1920 /* check if output reg modifier post-process */
1921 if (curOpcode
->num_params
> 0 && (pToken
[0] & D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
1922 if (pToken
[0] & D3DSP_WRITEMASK_0
) p
[0]->x
= d
.x
;
1923 if (pToken
[0] & D3DSP_WRITEMASK_1
) p
[0]->y
= d
.y
;
1924 if (pToken
[0] & D3DSP_WRITEMASK_2
) p
[0]->z
= d
.z
;
1925 if (pToken
[0] & D3DSP_WRITEMASK_3
) p
[0]->w
= d
.w
;
1928 TRACE_VSVECTOR(output
->oPos
);
1929 TRACE_VSVECTOR(output
->oD
[0]);
1930 TRACE_VSVECTOR(output
->oD
[1]);
1931 TRACE_VSVECTOR(output
->oT
[0]);
1932 TRACE_VSVECTOR(output
->oT
[1]);
1933 TRACE_VSVECTOR(R
[0]);
1934 TRACE_VSVECTOR(R
[1]);
1935 TRACE_VSVECTOR(R
[2]);
1936 TRACE_VSVECTOR(R
[3]);
1937 TRACE_VSVECTOR(R
[4]);
1938 TRACE_VSVECTOR(R
[5]);
1941 /* to next opcode token */
1942 pToken
+= curOpcode
->num_params
;
1945 TRACE("End of current instruction:\n");
1946 TRACE_VSVECTOR(output
->oPos
);
1947 TRACE_VSVECTOR(output
->oD
[0]);
1948 TRACE_VSVECTOR(output
->oD
[1]);
1949 TRACE_VSVECTOR(output
->oT
[0]);
1950 TRACE_VSVECTOR(output
->oT
[1]);
1951 TRACE_VSVECTOR(R
[0]);
1952 TRACE_VSVECTOR(R
[1]);
1953 TRACE_VSVECTOR(R
[2]);
1954 TRACE_VSVECTOR(R
[3]);
1955 TRACE_VSVECTOR(R
[4]);
1956 TRACE_VSVECTOR(R
[5]);
1959 #if 0 /* Must not be 1 in cvs */
1961 TRACE_VSVECTOR(output
->oPos
);
1962 TRACE_VSVECTOR(output
->oD
[0]);
1963 TRACE_VSVECTOR(output
->oD
[1]);
1964 TRACE_VSVECTOR(output
->oT
[0]);
1965 TRACE_VSVECTOR(output
->oT
[1]);
1970 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST FLOAT
*pConstantData
, UINT Vector4fCount
) {
1971 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1972 FIXME("(%p) : stub\n", This
);
1976 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader
*iface
, UINT StartRegister
, FLOAT
*pConstantData
, UINT Vector4fCount
) {
1977 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1978 FIXME("(%p) : stub\n", This
);
1982 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST
int *pConstantData
, UINT Vector4iCount
) {
1983 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1984 if (StartRegister
+ Vector4iCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
1985 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This
, StartRegister
);
1986 return D3DERR_INVALIDCALL
;
1988 if (NULL
== pConstantData
) {
1989 return D3DERR_INVALIDCALL
;
1991 FIXME("(%p) : stub\n", This
);
1995 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader
*iface
, UINT StartRegister
, int *pConstantData
, UINT Vector4iCount
) {
1996 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1997 TRACE("(%p) : C[%u] count=%u\n", This
, StartRegister
, Vector4iCount
);
1998 if (StartRegister
+ Vector4iCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
1999 return D3DERR_INVALIDCALL
;
2001 if (NULL
== pConstantData
) {
2002 return D3DERR_INVALIDCALL
;
2004 FIXME("(%p) : stub\n", This
);
2008 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST BOOL
*pConstantData
, UINT BoolCount
) {
2009 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2010 if (StartRegister
+ BoolCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
2011 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This
, StartRegister
);
2012 return D3DERR_INVALIDCALL
;
2014 if (NULL
== pConstantData
) {
2015 return D3DERR_INVALIDCALL
;
2017 FIXME("(%p) : stub\n", This
);
2021 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader
*iface
, UINT StartRegister
, BOOL
*pConstantData
, UINT BoolCount
) {
2022 IWineD3DVertexShaderImpl
* This
= (IWineD3DVertexShaderImpl
*)iface
;
2023 FIXME("(%p) : stub\n", This
);
2029 /* *******************************************
2030 IWineD3DVertexShader IUnknown parts follow
2031 ******************************************* */
2032 HRESULT WINAPI
IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader
*iface
, REFIID riid
, LPVOID
*ppobj
)
2034 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2035 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
2036 if (IsEqualGUID(riid
, &IID_IUnknown
)
2037 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
2038 || IsEqualGUID(riid
, &IID_IWineD3DBaseShader
)
2039 || IsEqualGUID(riid
, &IID_IWineD3DVertexShader
)) {
2040 IUnknown_AddRef(iface
);
2044 return E_NOINTERFACE
;
2047 ULONG WINAPI
IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader
*iface
) {
2048 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2049 TRACE("(%p) : AddRef increasing from %ld\n", This
, This
->ref
);
2050 return InterlockedIncrement(&This
->ref
);
2053 ULONG WINAPI
IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader
*iface
) {
2054 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2056 TRACE("(%p) : Releasing from %ld\n", This
, This
->ref
);
2057 ref
= InterlockedDecrement(&This
->ref
);
2059 if (This
->vertexDeclaration
) IWineD3DVertexDeclaration_Release(This
->vertexDeclaration
);
2060 HeapFree(GetProcessHeap(), 0, This
);
2065 /* *******************************************
2066 IWineD3DVertexShader IWineD3DVertexShader parts follow
2067 ******************************************* */
2069 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader
*iface
, IUnknown
** parent
){
2070 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2072 *parent
= This
->parent
;
2073 IUnknown_AddRef(*parent
);
2074 TRACE("(%p) : returning %p\n", This
, *parent
);
2078 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader
* iface
, IWineD3DDevice
**pDevice
){
2079 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2080 IWineD3DDevice_AddRef((IWineD3DDevice
*)This
->wineD3DDevice
);
2081 *pDevice
= (IWineD3DDevice
*)This
->wineD3DDevice
;
2082 TRACE("(%p) returning %p\n", This
, *pDevice
);
2086 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader
* impl
, VOID
* pData
, UINT
* pSizeOfData
) {
2087 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)impl
;
2088 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This
, pData
, pSizeOfData
);
2090 if (NULL
== pData
) {
2091 *pSizeOfData
= This
->baseShader
.functionLength
;
2094 if (*pSizeOfData
< This
->baseShader
.functionLength
) {
2095 *pSizeOfData
= This
->baseShader
.functionLength
;
2096 return D3DERR_MOREDATA
;
2098 if (NULL
== This
->baseShader
.function
) { /* no function defined */
2099 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This
, pData
);
2100 (*(DWORD
**) pData
) = NULL
;
2102 if(This
->baseShader
.functionLength
== 0){
2105 TRACE("(%p) : GetFunction copying to %p\n", This
, pData
);
2106 memcpy(pData
, This
->baseShader
.function
, This
->baseShader
.functionLength
);
2111 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
*iface
, CONST DWORD
*pFunction
) {
2112 IWineD3DVertexShaderImpl
*This
=(IWineD3DVertexShaderImpl
*)iface
;
2113 const DWORD
* pToken
= pFunction
;
2114 const SHADER_OPCODE
* curOpcode
= NULL
;
2117 TRACE("(%p) : Parsing programme\n", This
);
2119 if (NULL
!= pToken
) {
2120 while (D3DVS_END() != *pToken
) {
2121 if (vshader_is_version_token(*pToken
)) { /** version */
2122 TRACE("vs_%lu_%lu\n", (*pToken
>> 8) & 0x0F, (*pToken
& 0x0F));
2127 if (vshader_is_comment_token(*pToken
)) { /** comment */
2128 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
2130 TRACE("//%s\n", (char*)pToken
);
2131 pToken
+= comment_len
;
2132 len
+= comment_len
+ 1;
2135 curOpcode
= vshader_program_get_opcode(This
, *pToken
);
2138 if (NULL
== curOpcode
) {
2139 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2140 while (*pToken
& 0x80000000) {
2141 /* unknown current opcode ... */
2142 FIXME("unrecognized opcode: %08lx", *pToken
);
2149 if (curOpcode
->opcode
== D3DSIO_DCL
) {
2150 vshader_program_dump_decl_usage(This
, *pToken
);
2153 vshader_program_dump_vs_param(*pToken
, 0);
2157 if (curOpcode
->opcode
== D3DSIO_DEF
) {
2158 TRACE("def c%lu = ", *pToken
& 0xFF);
2161 TRACE("%f ,", *(float *)pToken
);
2164 TRACE("%f ,", *(float *)pToken
);
2167 TRACE("%f ,", *(float *)pToken
);
2170 TRACE("%f", *(float *)pToken
);
2174 TRACE("%s ", curOpcode
->name
);
2175 if (curOpcode
->num_params
> 0) {
2176 vshader_program_dump_vs_param(*pToken
, 0);
2179 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
2181 vshader_program_dump_vs_param(*pToken
, 1);
2190 This
->baseShader
.functionLength
= (len
+ 1) * sizeof(DWORD
);
2192 This
->baseShader
.functionLength
= 1; /* no Function defined use fixed function vertex processing */
2195 /* Generate HW shader in needed */
2196 if (NULL
!= pFunction
&& wined3d_settings
.vs_mode
== VS_HW
) {
2198 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface
, pFunction
);
2202 /* copy the function ... because it will certainly be released by application */
2203 if (NULL
!= pFunction
) {
2204 This
->baseShader
.function
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->baseShader
.functionLength
);
2205 memcpy((void *)This
->baseShader
.function
, pFunction
, This
->baseShader
.functionLength
);
2207 This
->baseShader
.function
= NULL
;
2212 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl
=
2214 /*** IUnknown methods ***/
2215 IWineD3DVertexShaderImpl_QueryInterface
,
2216 IWineD3DVertexShaderImpl_AddRef
,
2217 IWineD3DVertexShaderImpl_Release
,
2218 /*** IWineD3DBase methods ***/
2219 IWineD3DVertexShaderImpl_GetParent
,
2220 /*** IWineD3DBaseShader methods ***/
2221 IWineD3DVertexShaderImpl_SetFunction
,
2222 /*** IWineD3DVertexShader methods ***/
2223 IWineD3DVertexShaderImpl_GetDevice
,
2224 IWineD3DVertexShaderImpl_GetFunction