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
));
366 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
367 void vshader_def(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
, WINED3DSHADERVECTOR
* s3
) {
371 void vshader_call(WINED3DSHADERVECTOR
* d
) {
375 void vshader_callnz(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
379 void vshader_loop(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
383 void vshader_ret(void) {
387 void vshader_endloop(void) {
391 void vshader_dcl(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
395 void vshader_pow(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
399 void vshader_sng(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
403 void vshader_nrm(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
407 void vshader_sincos(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
411 void vshader_rep(WINED3DSHADERVECTOR
* d
) {
415 void vshader_endrep(void) {
419 void vshader_if(WINED3DSHADERVECTOR
* d
) {
423 void vshader_ifc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
427 void vshader_else(void) {
431 void vshader_label(WINED3DSHADERVECTOR
* d
) {
435 void vshader_endif(void) {
439 void vshader_break(void) {
443 void vshader_breakc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
447 void vshader_breakp(WINED3DSHADERVECTOR
* d
) {
451 void vshader_mova(WINED3DSHADERVECTOR
* d
) {
455 void vshader_defb(WINED3DSHADERVECTOR
* d
) {
459 void vshader_defi(WINED3DSHADERVECTOR
* d
) {
463 void vshader_texldd(WINED3DSHADERVECTOR
* d
) {
467 void vshader_setp(WINED3DSHADERVECTOR
* d
) {
471 void vshader_texldl(WINED3DSHADERVECTOR
* d
) {
476 void vshader_hw_map2gl(SHADER_OPCODE_ARG
* arg
);
477 void vshader_hw_dcl(SHADER_OPCODE_ARG
* arg
);
478 void vshader_hw_def(SHADER_OPCODE_ARG
* arg
);
479 void vshader_hw_mnxn(SHADER_OPCODE_ARG
* arg
);
482 * log, exp, frc, m*x* seems to be macros ins ... to see
484 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins
[] = {
487 {D3DSIO_NOP
, "nop", "NOP", 0, vshader_nop
, vshader_hw_map2gl
, NULL
, 0, 0},
488 {D3DSIO_MOV
, "mov", "MOV", 2, vshader_mov
, vshader_hw_map2gl
, NULL
, 0, 0},
489 {D3DSIO_ADD
, "add", "ADD", 3, vshader_add
, vshader_hw_map2gl
, NULL
, 0, 0},
490 {D3DSIO_SUB
, "sub", "SUB", 3, vshader_sub
, vshader_hw_map2gl
, NULL
, 0, 0},
491 {D3DSIO_MAD
, "mad", "MAD", 4, vshader_mad
, vshader_hw_map2gl
, NULL
, 0, 0},
492 {D3DSIO_MUL
, "mul", "MUL", 3, vshader_mul
, vshader_hw_map2gl
, NULL
, 0, 0},
493 {D3DSIO_RCP
, "rcp", "RCP", 2, vshader_rcp
, vshader_hw_map2gl
, NULL
, 0, 0},
494 {D3DSIO_RSQ
, "rsq", "RSQ", 2, vshader_rsq
, vshader_hw_map2gl
, NULL
, 0, 0},
495 {D3DSIO_DP3
, "dp3", "DP3", 3, vshader_dp3
, vshader_hw_map2gl
, NULL
, 0, 0},
496 {D3DSIO_DP4
, "dp4", "DP4", 3, vshader_dp4
, vshader_hw_map2gl
, NULL
, 0, 0},
497 {D3DSIO_MIN
, "min", "MIN", 3, vshader_min
, vshader_hw_map2gl
, NULL
, 0, 0},
498 {D3DSIO_MAX
, "max", "MAX", 3, vshader_max
, vshader_hw_map2gl
, NULL
, 0, 0},
499 {D3DSIO_SLT
, "slt", "SLT", 3, vshader_slt
, vshader_hw_map2gl
, NULL
, 0, 0},
500 {D3DSIO_SGE
, "sge", "SGE", 3, vshader_sge
, vshader_hw_map2gl
, NULL
, 0, 0},
501 {D3DSIO_ABS
, "abs", "ABS", 2, vshader_abs
, vshader_hw_map2gl
, NULL
, 0, 0},
502 {D3DSIO_EXP
, "exp", "EX2", 2, vshader_exp
, vshader_hw_map2gl
, NULL
, 0, 0},
503 {D3DSIO_LOG
, "log", "LG2", 2, vshader_log
, vshader_hw_map2gl
, NULL
, 0, 0},
504 {D3DSIO_EXPP
, "expp", "EXP", 2, vshader_expp
, vshader_hw_map2gl
, NULL
, 0, 0},
505 {D3DSIO_LOGP
, "logp", "LOG", 2, vshader_logp
, vshader_hw_map2gl
, NULL
, 0, 0},
506 {D3DSIO_LIT
, "lit", "LIT", 2, vshader_lit
, vshader_hw_map2gl
, NULL
, 0, 0},
507 {D3DSIO_DST
, "dst", "DST", 3, vshader_dst
, vshader_hw_map2gl
, NULL
, 0, 0},
508 {D3DSIO_LRP
, "lrp", "LRP", 4, vshader_lrp
, vshader_hw_map2gl
, NULL
, 0, 0},
509 {D3DSIO_FRC
, "frc", "FRC", 2, vshader_frc
, vshader_hw_map2gl
, NULL
, 0, 0},
510 {D3DSIO_POW
, "pow", "POW", 3, vshader_pow
, NULL
, NULL
, 0, 0},
511 {D3DSIO_CRS
, "crs", "XPS", 3, vshader_crs
, NULL
, NULL
, 0, 0},
512 /* TODO: sng can possibly be performed a s
515 {D3DSIO_SGN
, "sng", NULL
, 2, vshader_sng
, NULL
, NULL
, 0, 0},
516 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
519 MUL vec.xyz, vec, tmp;
520 but I think this is better because it accounts for w properly.
526 {D3DSIO_NRM
, "nrm", NULL
, 2, vshader_nrm
, NULL
, NULL
, 0, 0},
527 {D3DSIO_SINCOS
, "sincos", NULL
, 2, vshader_sincos
, NULL
, NULL
, 0, 0},
530 {D3DSIO_M4x4
, "m4x4", "undefined", 3, vshader_m4x4
, vshader_hw_mnxn
, NULL
, 0, 0},
531 {D3DSIO_M4x3
, "m4x3", "undefined", 3, vshader_m4x3
, vshader_hw_mnxn
, NULL
, 0, 0},
532 {D3DSIO_M3x4
, "m3x4", "undefined", 3, vshader_m3x4
, vshader_hw_mnxn
, NULL
, 0, 0},
533 {D3DSIO_M3x3
, "m3x3", "undefined", 3, vshader_m3x3
, vshader_hw_mnxn
, NULL
, 0, 0},
534 {D3DSIO_M3x2
, "m3x2", "undefined", 3, vshader_m3x2
, vshader_hw_mnxn
, NULL
, 0, 0},
536 /* Declare registers */
537 {D3DSIO_DCL
, "dcl", NULL
, 2, vshader_dcl
, vshader_hw_dcl
, NULL
, 0, 0},
539 /* Constant definitions */
540 {D3DSIO_DEF
, "def", NULL
, 5, vshader_def
, vshader_hw_def
, NULL
, 0, 0},
541 {D3DSIO_DEFB
, "defb", GLNAME_REQUIRE_GLSL
, 2, vshader_defb
, NULL
, NULL
, 0, 0},
542 {D3DSIO_DEFI
, "defi", GLNAME_REQUIRE_GLSL
, 2, vshader_defi
, NULL
, NULL
, 0, 0},
544 /* Flow control - requires GLSL or software shaders */
545 {D3DSIO_REP
, "rep", GLNAME_REQUIRE_GLSL
, 1, vshader_rep
, NULL
, NULL
, 0, 0},
546 {D3DSIO_ENDREP
, "endrep", GLNAME_REQUIRE_GLSL
, 0, vshader_endrep
, NULL
, NULL
, 0, 0},
547 {D3DSIO_IF
, "if", GLNAME_REQUIRE_GLSL
, 1, vshader_if
, NULL
, NULL
, 0, 0},
548 {D3DSIO_IFC
, "ifc", GLNAME_REQUIRE_GLSL
, 2, vshader_ifc
, NULL
, NULL
, 0, 0},
549 {D3DSIO_ELSE
, "else", GLNAME_REQUIRE_GLSL
, 0, vshader_else
, NULL
, NULL
, 0, 0},
550 {D3DSIO_ENDIF
, "endif", GLNAME_REQUIRE_GLSL
, 0, vshader_endif
, NULL
, NULL
, 0, 0},
551 {D3DSIO_BREAK
, "break", GLNAME_REQUIRE_GLSL
, 0, vshader_break
, NULL
, NULL
, 0, 0},
552 {D3DSIO_BREAKC
, "breakc", GLNAME_REQUIRE_GLSL
, 2, vshader_breakc
, NULL
, NULL
, 0, 0},
553 {D3DSIO_BREAKP
, "breakp", GLNAME_REQUIRE_GLSL
, 1, vshader_breakp
, NULL
, NULL
, 0, 0},
554 {D3DSIO_CALL
, "call", GLNAME_REQUIRE_GLSL
, 1, vshader_call
, NULL
, NULL
, 0, 0},
555 {D3DSIO_CALLNZ
, "callnz", GLNAME_REQUIRE_GLSL
, 2, vshader_callnz
, NULL
, NULL
, 0, 0},
556 {D3DSIO_LOOP
, "loop", GLNAME_REQUIRE_GLSL
, 2, vshader_loop
, NULL
, NULL
, 0, 0},
557 {D3DSIO_RET
, "ret", GLNAME_REQUIRE_GLSL
, 0, vshader_ret
, NULL
, NULL
, 0, 0},
558 {D3DSIO_ENDLOOP
, "endloop", GLNAME_REQUIRE_GLSL
, 0, vshader_endloop
, NULL
, NULL
, 0, 0},
559 {D3DSIO_LABEL
, "label", GLNAME_REQUIRE_GLSL
, 1, vshader_label
, NULL
, NULL
, 0, 0},
561 {D3DSIO_MOVA
, "mova", GLNAME_REQUIRE_GLSL
, 2, vshader_mova
, NULL
, NULL
, 0, 0},
562 {D3DSIO_SETP
, "setp", GLNAME_REQUIRE_GLSL
, 2, vshader_setp
, NULL
, NULL
, 0, 0},
563 {D3DSIO_TEXLDL
, "texdl", GLNAME_REQUIRE_GLSL
, 2, vshader_texldl
, NULL
, NULL
, 0, 0},
564 {0, NULL
, NULL
, 0, NULL
, NULL
, 0, 0}
567 inline static void vshader_program_dump_vs_param(const DWORD param
, int input
) {
568 static const char* rastout_reg_names
[] = { "oPos", "oFog", "oPts" };
569 static const char swizzle_reg_chars
[] = "xyzw";
571 DWORD reg
= param
& D3DSP_REGNUM_MASK
;
572 DWORD regtype
= shader_get_regtype(param
);
574 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) TRACE("-");
584 TRACE("c%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
586 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
590 TRACE("%s", rastout_reg_names
[reg
]);
595 case D3DSPR_TEXCRDOUT
:
598 case D3DSPR_CONSTINT
:
599 TRACE("i%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
601 case D3DSPR_CONSTBOOL
:
602 TRACE("b%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
608 TRACE("aL%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
614 FIXME("Unknown %lu reg %lu\n",regtype
, reg
);
619 /** operand output */
620 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
621 if (param
& D3DSP_WRITEMASK_0
) TRACE(".x");
622 if (param
& D3DSP_WRITEMASK_1
) TRACE(".y");
623 if (param
& D3DSP_WRITEMASK_2
) TRACE(".z");
624 if (param
& D3DSP_WRITEMASK_3
) TRACE(".w");
628 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
629 DWORD swizzle_x
= swizzle
& 0x03;
630 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
631 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
632 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
634 * swizzle bits fields:
637 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) != swizzle
) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
638 if (swizzle_x
== swizzle_y
&&
639 swizzle_x
== swizzle_z
&&
640 swizzle_x
== swizzle_w
) {
641 TRACE(".%c", swizzle_reg_chars
[swizzle_x
]);
644 swizzle_reg_chars
[swizzle_x
],
645 swizzle_reg_chars
[swizzle_y
],
646 swizzle_reg_chars
[swizzle_z
],
647 swizzle_reg_chars
[swizzle_w
]);
653 inline static BOOL
vshader_is_version_token(DWORD token
) {
654 return 0xFFFE0000 == (token
& 0xFFFE0000);
657 inline static BOOL
vshader_is_comment_token(DWORD token
) {
658 return D3DSIO_COMMENT
== (token
& D3DSI_OPCODE_MASK
);
661 inline static void vshader_program_add_output_param_swizzle(const DWORD param
, int is_color
, char *hwLine
) {
662 /** operand output */
663 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
665 if (param
& D3DSP_WRITEMASK_0
) { strcat(hwLine
, "x"); }
666 if (param
& D3DSP_WRITEMASK_1
) { strcat(hwLine
, "y"); }
667 if (param
& D3DSP_WRITEMASK_2
) { strcat(hwLine
, "z"); }
668 if (param
& D3DSP_WRITEMASK_3
) { strcat(hwLine
, "w"); }
672 inline static void vshader_program_add_input_param_swizzle(const DWORD param
, int is_color
, char *hwLine
) {
673 static const char swizzle_reg_chars_color_fix
[] = "zyxw";
674 static const char swizzle_reg_chars
[] = "xyzw";
675 const char* swizzle_regs
= NULL
;
679 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
680 DWORD swizzle_x
= swizzle
& 0x03;
681 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
682 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
683 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
686 swizzle_regs
= swizzle_reg_chars_color_fix
;
688 swizzle_regs
= swizzle_reg_chars
;
692 * swizzle bits fields:
695 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) == swizzle
) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
697 sprintf(tmpReg
, ".%c%c%c%c",
698 swizzle_regs
[swizzle_x
],
699 swizzle_regs
[swizzle_y
],
700 swizzle_regs
[swizzle_z
],
701 swizzle_regs
[swizzle_w
]);
702 strcat(hwLine
, tmpReg
);
706 if (swizzle_x
== swizzle_y
&&
707 swizzle_x
== swizzle_z
&&
708 swizzle_x
== swizzle_w
)
710 sprintf(tmpReg
, ".%c", swizzle_regs
[swizzle_x
]);
711 strcat(hwLine
, tmpReg
);
713 sprintf(tmpReg
, ".%c%c%c%c",
714 swizzle_regs
[swizzle_x
],
715 swizzle_regs
[swizzle_y
],
716 swizzle_regs
[swizzle_z
],
717 swizzle_regs
[swizzle_w
]);
718 strcat(hwLine
, tmpReg
);
722 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl
*This
, const DWORD param
, BOOL is_input
, char *hwLine
) {
723 /* oPos, oFog and oPts in D3D */
724 static const char* hwrastout_reg_names
[] = { "result.position", "result.fogcoord", "result.pointsize" };
726 DWORD reg
= param
& D3DSP_REGNUM_MASK
;
727 DWORD regtype
= shader_get_regtype(param
);
729 BOOL is_color
= FALSE
;
731 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) {
732 strcat(hwLine
, " -");
739 sprintf(tmpReg
, "R%lu", reg
);
740 strcat(hwLine
, tmpReg
);
743 if (reg
== This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DIFFUSE
]
744 || reg
== This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SPECULAR
]) {
747 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
748 if (This
->namedArrays
) {
749 sprintf(tmpReg
, "namedVertex%lu", reg
);
751 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
752 sprintf(tmpReg
, "vertex.attrib[%lu]", reg
);
754 strcat(hwLine
, tmpReg
);
757 /* FIXME: some constants are named so we need a constants map*/
758 if (This
->constantsUsedBitmap
[reg
] == VS_CONSTANT_CONSTANT
) {
759 if (param
& D3DVS_ADDRMODE_RELATIVE
) {
760 FIXME("Relative addressing not expected for a named constant %lu\n", reg
);
762 sprintf(tmpReg
, "const%lu", reg
);
764 sprintf(tmpReg
, "C[%s%lu]", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "A0.x + " : "", reg
);
766 strcat(hwLine
, tmpReg
);
768 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
769 sprintf(tmpReg
, "A%lu", reg
);
770 strcat(hwLine
, tmpReg
);
773 sprintf(tmpReg
, "%s", hwrastout_reg_names
[reg
]);
774 strcat(hwLine
, tmpReg
);
778 strcat(hwLine
, "result.color.primary");
780 strcat(hwLine
, "result.color.secondary");
783 case D3DSPR_TEXCRDOUT
:
784 sprintf(tmpReg
, "result.texcoord[%lu]", reg
);
785 strcat(hwLine
, tmpReg
);
788 FIXME("Unknown reg type %ld %ld\n", regtype
, reg
);
793 vshader_program_add_output_param_swizzle(param
, is_color
, hwLine
);
795 vshader_program_add_input_param_swizzle(param
, is_color
, hwLine
);
799 static void parse_decl_usage(IWineD3DVertexShaderImpl
*This
, INT usage
, INT arrayNo
)
801 switch(usage
& 0xFFFF) {
802 case D3DDECLUSAGE_POSITION
:
803 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
804 TRACE("Setting position to %d\n", arrayNo
);
805 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITION
] = arrayNo
;
806 This
->namedArrays
= TRUE
;
808 /* TODO: position indexes go from 0-8!!*/
809 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
810 /* robots uses positions up to 8, the position arrays are just packed.*/
811 if ((usage
& 0xF0000) >> 16 > 1) {
812 TRACE("Loaded for position %d (greater than 2)\n", (usage
& 0xF0000) >> 16);
814 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITION2
+ ((usage
& 0xF0000) >> 16) -1] = arrayNo
;
815 This
->declaredArrays
= TRUE
;
818 case D3DDECLUSAGE_BLENDINDICES
:
819 /* not supported by openGL */
820 TRACE("Setting BLENDINDICES to %d\n", arrayNo
);
821 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BLENDINDICES
] = arrayNo
;
822 This
->declaredArrays
= TRUE
;
823 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
825 case D3DDECLUSAGE_BLENDWEIGHT
:
826 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo
);
827 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BLENDWEIGHT
] = arrayNo
;
828 This
->namedArrays
= TRUE
;
829 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
831 case D3DDECLUSAGE_NORMAL
:
832 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
833 TRACE("Setting normal to %d\n", arrayNo
);
834 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_NORMAL
] = arrayNo
;
835 This
->namedArrays
= TRUE
;
837 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
838 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_NORMAL2
] = arrayNo
;
839 This
->declaredArrays
= TRUE
;
842 case D3DDECLUSAGE_PSIZE
:
843 TRACE("Setting PSIZE to %d\n", arrayNo
);
844 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_PSIZE
] = arrayNo
;
845 This
->namedArrays
= TRUE
;
846 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
848 case D3DDECLUSAGE_COLOR
:
849 if((usage
& 0xF0000) >> 16 == 0) {
850 TRACE("Setting DIFFUSE to %d\n", arrayNo
);
851 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DIFFUSE
] = arrayNo
;
852 This
->namedArrays
= TRUE
;
854 TRACE("Setting SPECULAR to %d\n", arrayNo
);
855 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SPECULAR
] = arrayNo
;
856 This
->namedArrays
= TRUE
;
859 case D3DDECLUSAGE_TEXCOORD
:
860 This
->namedArrays
= TRUE
;
861 /* only 7 texture coords have been designed for, so run a quick sanity check */
862 if ((usage
& 0xF0000) >> 16 > 7) {
863 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This
, (usage
& 0xF0000) >> 16);
865 TRACE("Setting TEXCOORD %d to %d\n", ((usage
& 0xF0000) >> 16), arrayNo
);
866 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TEXCOORD0
+ ((usage
& 0xF0000) >> 16)] = arrayNo
;
869 /* The following aren't supported by openGL,
870 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
871 this should be caught in the first pass */
872 case D3DDECLUSAGE_TANGENT
:
873 TRACE("Setting TANGENT to %d\n", arrayNo
);
874 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TANGENT
] = arrayNo
;
875 This
->declaredArrays
= TRUE
;
877 case D3DDECLUSAGE_BINORMAL
:
878 TRACE("Setting BINORMAL to %d\n", arrayNo
);
879 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BINORMAL
] = arrayNo
;
880 This
->declaredArrays
= TRUE
;
882 case D3DDECLUSAGE_TESSFACTOR
:
883 TRACE("Setting TESSFACTOR to %d\n", arrayNo
);
884 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TESSFACTOR
] = arrayNo
;
885 This
->declaredArrays
= TRUE
;
887 case D3DDECLUSAGE_POSITIONT
:
888 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
889 FIXME("Setting positiont to %d\n", arrayNo
);
890 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITIONT
] = arrayNo
;
891 This
->namedArrays
= TRUE
;
893 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
894 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITIONT2
] = arrayNo
;
895 This
->declaredArrays
= TRUE
;
896 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
899 case D3DDECLUSAGE_FOG
:
900 /* supported by OpenGL */
901 TRACE("Setting FOG to %d\n", arrayNo
);
902 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_FOG
] = arrayNo
;
903 This
->namedArrays
= TRUE
;
905 case D3DDECLUSAGE_DEPTH
:
906 TRACE("Setting DEPTH to %d\n", arrayNo
);
907 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DEPTH
] = arrayNo
;
908 This
->declaredArrays
= TRUE
;
910 case D3DDECLUSAGE_SAMPLE
:
911 TRACE("Setting SAMPLE to %d\n", arrayNo
);
912 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SAMPLE
] = arrayNo
;
913 This
->declaredArrays
= TRUE
;
916 FIXME("Unrecognised dcl %08x", usage
& 0xFFFF);
920 void vshader_set_version(
921 IWineD3DVertexShaderImpl
*This
,
924 DWORD major
= (version
>> 8) & 0x0F;
925 DWORD minor
= version
& 0x0F;
927 This
->baseShader
.hex_version
= version
;
928 This
->baseShader
.version
= major
* 10 + minor
;
929 TRACE("vs_%lu_%lu\n", major
, minor
);
931 This
->baseShader
.limits
.texture
= 0;
933 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
934 This
->baseShader
.limits
.constant_float
= WINED3D_VSHADER_MAX_CONSTANTS
;
936 switch (This
->baseShader
.version
) {
938 case 11: This
->baseShader
.limits
.temporary
= 12;
939 This
->baseShader
.limits
.constant_bool
= 0;
940 This
->baseShader
.limits
.constant_int
= 0;
941 This
->baseShader
.limits
.address
= 1;
945 case 21: This
->baseShader
.limits
.temporary
= 12;
946 This
->baseShader
.limits
.constant_bool
= 16;
947 This
->baseShader
.limits
.constant_int
= 16;
948 This
->baseShader
.limits
.address
= 1;
951 case 30: This
->baseShader
.limits
.temporary
= 32;
952 This
->baseShader
.limits
.constant_bool
= 32;
953 This
->baseShader
.limits
.constant_int
= 32;
954 This
->baseShader
.limits
.address
= 1;
957 default: This
->baseShader
.limits
.temporary
= 12;
958 This
->baseShader
.limits
.constant_bool
= 0;
959 This
->baseShader
.limits
.constant_int
= 0;
960 This
->baseShader
.limits
.address
= 1;
961 FIXME("Unrecognized vertex shader version %lx!\n", version
);
965 /* Map the opcode 1-to-1 to the GL code */
966 void vshader_hw_map2gl(SHADER_OPCODE_ARG
* arg
) {
968 IWineD3DVertexShaderImpl
* This
= (IWineD3DVertexShaderImpl
*) arg
->shader
;
969 CONST SHADER_OPCODE
* curOpcode
= arg
->opcode
;
970 SHADER_BUFFER
* buffer
= arg
->buffer
;
971 DWORD dst
= arg
->dst
;
972 DWORD
* src
= arg
->src
;
974 DWORD dst_regtype
= shader_get_regtype(dst
);
978 if (curOpcode
->opcode
== D3DSIO_MOV
&& dst_regtype
== D3DSPR_ADDR
)
979 strcpy(tmpLine
, "ARL");
981 strcpy(tmpLine
, curOpcode
->glname
);
983 if (curOpcode
->num_params
> 0) {
984 vshader_program_add_param(This
, dst
, FALSE
, tmpLine
);
985 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
986 strcat(tmpLine
, ",");
987 vshader_program_add_param(This
, src
[i
-1], TRUE
, tmpLine
);
990 shader_addline(buffer
, "%s;\n", tmpLine
);
993 void vshader_hw_dcl(SHADER_OPCODE_ARG
* arg
) {
995 DWORD dst
= arg
->dst
;
996 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*) arg
->shader
;
998 SHADER_BUFFER
* buffer
= arg
->buffer
;
1000 if (This
->namedArrays
) {
1001 const char* attribName
= "undefined";
1002 switch(dst
& 0xFFFF) {
1003 case D3DDECLUSAGE_POSITION
:
1004 attribName
= "vertex.position";
1006 case D3DDECLUSAGE_BLENDINDICES
:
1007 /* not supported by openGL */
1008 attribName
= "vertex.blend";
1010 case D3DDECLUSAGE_BLENDWEIGHT
:
1011 attribName
= "vertex.weight";
1013 case D3DDECLUSAGE_NORMAL
:
1014 attribName
= "vertex.normal";
1016 case D3DDECLUSAGE_PSIZE
:
1017 attribName
= "vertex.psize";
1019 case D3DDECLUSAGE_COLOR
:
1020 if((dst
& 0xF0000) >> 16 == 0) {
1021 attribName
= "vertex.color";
1023 attribName
= "vertex.color.secondary";
1026 case D3DDECLUSAGE_TEXCOORD
:
1030 sprintf(tmpChar
,"vertex.texcoord[%lu]",(dst
& 0xF0000) >> 16);
1031 attribName
= tmpChar
;
1034 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1035 case D3DDECLUSAGE_TANGENT
:
1036 attribName
= "vertex.tangent";
1038 case D3DDECLUSAGE_BINORMAL
:
1039 attribName
= "vertex.binormal";
1041 case D3DDECLUSAGE_TESSFACTOR
:
1042 attribName
= "vertex.tessfactor";
1044 case D3DDECLUSAGE_POSITIONT
:
1045 attribName
= "vertex.possitionT";
1047 case D3DDECLUSAGE_FOG
:
1048 attribName
= "vertex.fogcoord";
1050 case D3DDECLUSAGE_DEPTH
:
1051 attribName
= "vertex.depth";
1053 case D3DDECLUSAGE_SAMPLE
:
1054 attribName
= "vertex.sample";
1057 FIXME("Unrecognised dcl %08lx", dst
& 0xFFFF);
1060 sprintf(tmpLine
, "ATTRIB ");
1061 vshader_program_add_param(This
, dst
, FALSE
, tmpLine
);
1062 if (This
->namedArrays
)
1063 shader_addline(buffer
, "%s = %s;\n", tmpLine
, attribName
);
1068 void vshader_hw_def(SHADER_OPCODE_ARG
* arg
) {
1070 IWineD3DVertexShaderImpl
* shader
= (IWineD3DVertexShaderImpl
*) arg
->shader
;
1071 SHADER_BUFFER
* buffer
= arg
->buffer
;
1072 DWORD reg
= arg
->dst
;
1074 shader_addline(buffer
,
1075 "PARAM const%lu = { %f, %f, %f, %f };\n", reg
& 0xFF,
1076 *((const float *)(arg
->src
+ 0)),
1077 *((const float *)(arg
->src
+ 1)),
1078 *((const float *)(arg
->src
+ 2)),
1079 *((const float *)(arg
->src
+ 3)) );
1081 shader
->constantsUsedBitmap
[reg
& 0xFF] = VS_CONSTANT_CONSTANT
;
1084 /** Handles transforming all D3DSIO_M?x? opcodes for
1085 Vertex shaders to ARB_vertex_program codes */
1086 void vshader_hw_mnxn(SHADER_OPCODE_ARG
* arg
) {
1089 int nComponents
= 0;
1090 SHADER_OPCODE_ARG tmpArg
;
1092 /* Set constants for the temporary argument */
1093 tmpArg
.shader
= arg
->shader
;
1094 tmpArg
.buffer
= arg
->buffer
;
1095 tmpArg
.src
[0] = arg
->src
[0];
1097 switch(arg
->opcode
->opcode
) {
1100 tmpArg
.opcode
= &IWineD3DVertexShaderImpl_shader_ins
[D3DSIO_DP4
];
1104 tmpArg
.opcode
= &IWineD3DVertexShaderImpl_shader_ins
[D3DSIO_DP4
];
1108 tmpArg
.opcode
= &IWineD3DVertexShaderImpl_shader_ins
[D3DSIO_DP3
];
1112 tmpArg
.opcode
= &IWineD3DVertexShaderImpl_shader_ins
[D3DSIO_DP3
];
1116 tmpArg
.opcode
= &IWineD3DVertexShaderImpl_shader_ins
[D3DSIO_DP3
];
1122 for (i
= 0; i
< nComponents
; i
++) {
1123 tmpArg
.dst
= ((arg
->dst
) & ~D3DSP_WRITEMASK_ALL
)|(D3DSP_WRITEMASK_0
<<i
);
1124 tmpArg
.src
[1] = arg
->src
[1]+i
;
1125 vshader_hw_map2gl(&tmpArg
);
1129 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1130 or GLSL and send it to the card */
1131 inline static VOID
IWineD3DVertexShaderImpl_GenerateShader(
1132 IWineD3DVertexShader
*iface
,
1133 CONST DWORD
*pFunction
) {
1135 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1136 SHADER_BUFFER buffer
;
1138 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1139 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1140 if (This
->device
->fixupVertexBufferSize
< SHADER_PGMSIZE
) {
1141 HeapFree(GetProcessHeap(), 0, This
->fixupVertexBuffer
);
1142 This
->fixupVertexBuffer
= HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE
);
1143 This
->fixupVertexBufferSize
= PGMSIZE
;
1144 This
->fixupVertexBuffer
[0] = 0;
1146 buffer
.buffer
= This
->device
->fixupVertexBuffer
;
1148 buffer
.buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, SHADER_PGMSIZE
);
1153 /* TODO: Optionally, generate the GLSL shader instead */
1154 if (GL_SUPPORT(ARB_VERTEX_PROGRAM
)) {
1155 /* Create the hw ARB shader */
1156 shader_addline(&buffer
, "!!ARBvp1.0\n");
1158 /* Mesa supports only 95 constants */
1159 if (GL_VEND(MESA
) || GL_VEND(WINE
))
1160 This
->baseShader
.limits
.constant_float
=
1161 min(95, This
->baseShader
.limits
.constant_float
);
1163 shader_addline(&buffer
, "PARAM C[%d] = { program.env[0..%d] };\n",
1164 This
->baseShader
.limits
.constant_float
,
1165 This
->baseShader
.limits
.constant_float
- 1);
1167 /** Call the base shader generation routine to generate most
1168 of the vertex shader string for us */
1169 generate_base_shader( (IWineD3DBaseShader
*) This
, &buffer
, pFunction
);
1171 shader_addline(&buffer
, "END\n\0");
1173 /* TODO: change to resource.glObjectHandle or something like that */
1174 GL_EXTCALL(glGenProgramsARB(1, &This
->baseShader
.prgId
));
1176 TRACE("Creating a hw vertex shader, prg=%d\n", This
->baseShader
.prgId
);
1177 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, This
->baseShader
.prgId
));
1179 TRACE("Created hw vertex shader, prg=%d\n", This
->baseShader
.prgId
);
1180 /* Create the program and check for errors */
1181 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
,
1182 buffer
.bsize
, buffer
.buffer
));
1184 if (glGetError() == GL_INVALID_OPERATION
) {
1186 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB
, &errPos
);
1187 FIXME("HW VertexShader Error at position %d: %s\n",
1188 errPos
, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB
)));
1189 This
->baseShader
.prgId
= -1;
1193 #if 1 /* if were using the data buffer of device then we don't need to free it */
1194 HeapFree(GetProcessHeap(), 0, buffer
.buffer
);
1198 BOOL
IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader
* iface
, WINEVSHADERINPUTDATA
* input
, WINEVSHADEROUTPUTDATA
* output
) {
1200 * TODO: use the NV_vertex_program (or 1_1) extension
1201 * and specifics vendors (ARB_vertex_program??) variants for it
1206 HRESULT WINAPI
IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader
* iface
, WINEVSHADERINPUTDATA
* input
, WINEVSHADEROUTPUTDATA
* output
) {
1207 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1209 /** Vertex Shader Temporary Registers */
1210 WINED3DSHADERVECTOR R
[12];
1211 /*D3DSHADERSCALAR A0;*/
1212 WINED3DSHADERVECTOR A
[1];
1213 /** temporary Vector for modifier management */
1214 WINED3DSHADERVECTOR d
;
1215 WINED3DSHADERVECTOR s
[3];
1217 const DWORD
* pToken
= This
->baseShader
.function
;
1218 const SHADER_OPCODE
* curOpcode
= NULL
;
1219 /** functions parameters */
1220 WINED3DSHADERVECTOR
* p
[4];
1221 WINED3DSHADERVECTOR
* p_send
[4];
1224 /** init temporary register */
1225 memset(R
, 0, 12 * sizeof(WINED3DSHADERVECTOR
));
1227 /* vshader_program_parse(vshader); */
1228 #if 0 /* Must not be 1 in cvs */
1230 TRACE_VSVECTOR(This
->data
->C
[0]);
1231 TRACE_VSVECTOR(This
->data
->C
[1]);
1232 TRACE_VSVECTOR(This
->data
->C
[2]);
1233 TRACE_VSVECTOR(This
->data
->C
[3]);
1234 TRACE_VSVECTOR(This
->data
->C
[4]);
1235 TRACE_VSVECTOR(This
->data
->C
[5]);
1236 TRACE_VSVECTOR(This
->data
->C
[6]);
1237 TRACE_VSVECTOR(This
->data
->C
[7]);
1238 TRACE_VSVECTOR(This
->data
->C
[8]);
1239 TRACE_VSVECTOR(This
->data
->C
[64]);
1240 TRACE_VSVECTOR(input
->V
[D3DVSDE_POSITION
]);
1241 TRACE_VSVECTOR(input
->V
[D3DVSDE_BLENDWEIGHT
]);
1242 TRACE_VSVECTOR(input
->V
[D3DVSDE_BLENDINDICES
]);
1243 TRACE_VSVECTOR(input
->V
[D3DVSDE_NORMAL
]);
1244 TRACE_VSVECTOR(input
->V
[D3DVSDE_PSIZE
]);
1245 TRACE_VSVECTOR(input
->V
[D3DVSDE_DIFFUSE
]);
1246 TRACE_VSVECTOR(input
->V
[D3DVSDE_SPECULAR
]);
1247 TRACE_VSVECTOR(input
->V
[D3DVSDE_TEXCOORD0
]);
1248 TRACE_VSVECTOR(input
->V
[D3DVSDE_TEXCOORD1
]);
1251 TRACE_VSVECTOR(vshader
->data
->C
[64]);
1252 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1254 /* the first dword is the version tag */
1255 /* TODO: parse it */
1257 if (vshader_is_version_token(*pToken
)) { /** version */
1260 while (D3DVS_END() != *pToken
) {
1261 if (vshader_is_comment_token(*pToken
)) { /** comment */
1262 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1264 pToken
+= comment_len
;
1267 curOpcode
= shader_get_opcode((IWineD3DBaseShader
*) This
, *pToken
);
1269 if (NULL
== curOpcode
) {
1271 /* unknown current opcode ... */
1272 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1273 while (*pToken
& 0x80000000) {
1275 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken
- 1) - This
->baseShader
.function
, *(pToken
- 1));
1277 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken
- This
->baseShader
.function
, *pToken
);
1278 vshader_program_dump_vs_param(*pToken
, i
);
1285 if (curOpcode
->num_params
> 0) {
1286 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1287 for (i
= 0; i
< curOpcode
->num_params
; ++i
) {
1288 DWORD reg
= pToken
[i
] & D3DSP_REGNUM_MASK
;
1289 DWORD regtype
= shader_get_regtype(pToken
[i
]);
1293 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1297 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1298 p
[i
] = &input
->V
[reg
];
1301 if (pToken
[i
] & D3DVS_ADDRMODE_RELATIVE
) {
1302 p
[i
] = &This
->data
->C
[(DWORD
) A
[0].x
+ reg
];
1304 p
[i
] = &This
->data
->C
[reg
];
1307 case D3DSPR_ADDR
: /* case D3DSPR_TEXTURE: */
1309 ERR("cannot handle address registers != a0, forcing use of a0\n");
1312 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1315 case D3DSPR_RASTOUT
:
1317 case D3DSRO_POSITION
:
1318 p
[i
] = &output
->oPos
;
1321 p
[i
] = &output
->oFog
;
1323 case D3DSRO_POINT_SIZE
:
1324 p
[i
] = &output
->oPts
;
1328 case D3DSPR_ATTROUT
:
1329 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1330 p
[i
] = &output
->oD
[reg
];
1332 case D3DSPR_TEXCRDOUT
:
1333 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1334 p
[i
] = &output
->oT
[reg
];
1336 /* TODO Decls and defs */
1345 if (i
> 0) { /* input reg */
1346 DWORD swizzle
= (pToken
[i
] & D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
1347 UINT isNegative
= ((pToken
[i
] & D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
);
1349 if (!isNegative
&& (D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) == swizzle
) {
1350 /* TRACE("p[%d] not swizzled\n", i); */
1353 DWORD swizzle_x
= swizzle
& 0x03;
1354 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
1355 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
1356 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
1357 /* TRACE("p[%d] swizzled\n", i); */
1358 float* tt
= (float*) p
[i
];
1359 s
[i
].x
= (isNegative
) ? -tt
[swizzle_x
] : tt
[swizzle_x
];
1360 s
[i
].y
= (isNegative
) ? -tt
[swizzle_y
] : tt
[swizzle_y
];
1361 s
[i
].z
= (isNegative
) ? -tt
[swizzle_z
] : tt
[swizzle_z
];
1362 s
[i
].w
= (isNegative
) ? -tt
[swizzle_w
] : tt
[swizzle_w
];
1365 } else { /* output reg */
1366 if ((pToken
[i
] & D3DSP_WRITEMASK_ALL
) == D3DSP_WRITEMASK_ALL
) {
1369 p_send
[i
] = &d
; /* to be post-processed for modifiers management */
1375 switch (curOpcode
->num_params
) {
1377 curOpcode
->soft_fct();
1380 curOpcode
->soft_fct(p_send
[0]);
1383 curOpcode
->soft_fct(p_send
[0], p_send
[1]);
1386 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2]);
1389 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3]);
1392 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3], p_send
[4]);
1395 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3], p_send
[4], p_send
[5]);
1398 ERR("%s too many params: %u\n", curOpcode
->name
, curOpcode
->num_params
);
1401 /* check if output reg modifier post-process */
1402 if (curOpcode
->num_params
> 0 && (pToken
[0] & D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
1403 if (pToken
[0] & D3DSP_WRITEMASK_0
) p
[0]->x
= d
.x
;
1404 if (pToken
[0] & D3DSP_WRITEMASK_1
) p
[0]->y
= d
.y
;
1405 if (pToken
[0] & D3DSP_WRITEMASK_2
) p
[0]->z
= d
.z
;
1406 if (pToken
[0] & D3DSP_WRITEMASK_3
) p
[0]->w
= d
.w
;
1409 TRACE_VSVECTOR(output
->oPos
);
1410 TRACE_VSVECTOR(output
->oD
[0]);
1411 TRACE_VSVECTOR(output
->oD
[1]);
1412 TRACE_VSVECTOR(output
->oT
[0]);
1413 TRACE_VSVECTOR(output
->oT
[1]);
1414 TRACE_VSVECTOR(R
[0]);
1415 TRACE_VSVECTOR(R
[1]);
1416 TRACE_VSVECTOR(R
[2]);
1417 TRACE_VSVECTOR(R
[3]);
1418 TRACE_VSVECTOR(R
[4]);
1419 TRACE_VSVECTOR(R
[5]);
1422 /* to next opcode token */
1423 pToken
+= curOpcode
->num_params
;
1426 TRACE("End of current instruction:\n");
1427 TRACE_VSVECTOR(output
->oPos
);
1428 TRACE_VSVECTOR(output
->oD
[0]);
1429 TRACE_VSVECTOR(output
->oD
[1]);
1430 TRACE_VSVECTOR(output
->oT
[0]);
1431 TRACE_VSVECTOR(output
->oT
[1]);
1432 TRACE_VSVECTOR(R
[0]);
1433 TRACE_VSVECTOR(R
[1]);
1434 TRACE_VSVECTOR(R
[2]);
1435 TRACE_VSVECTOR(R
[3]);
1436 TRACE_VSVECTOR(R
[4]);
1437 TRACE_VSVECTOR(R
[5]);
1440 #if 0 /* Must not be 1 in cvs */
1442 TRACE_VSVECTOR(output
->oPos
);
1443 TRACE_VSVECTOR(output
->oD
[0]);
1444 TRACE_VSVECTOR(output
->oD
[1]);
1445 TRACE_VSVECTOR(output
->oT
[0]);
1446 TRACE_VSVECTOR(output
->oT
[1]);
1451 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST FLOAT
*pConstantData
, UINT Vector4fCount
) {
1452 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1453 FIXME("(%p) : stub\n", This
);
1457 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader
*iface
, UINT StartRegister
, FLOAT
*pConstantData
, UINT Vector4fCount
) {
1458 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1459 FIXME("(%p) : stub\n", This
);
1463 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST
int *pConstantData
, UINT Vector4iCount
) {
1464 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1465 if (StartRegister
+ Vector4iCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
1466 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This
, StartRegister
);
1467 return WINED3DERR_INVALIDCALL
;
1469 if (NULL
== pConstantData
) {
1470 return WINED3DERR_INVALIDCALL
;
1472 FIXME("(%p) : stub\n", This
);
1476 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader
*iface
, UINT StartRegister
, int *pConstantData
, UINT Vector4iCount
) {
1477 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1478 TRACE("(%p) : C[%u] count=%u\n", This
, StartRegister
, Vector4iCount
);
1479 if (StartRegister
+ Vector4iCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
1480 return WINED3DERR_INVALIDCALL
;
1482 if (NULL
== pConstantData
) {
1483 return WINED3DERR_INVALIDCALL
;
1485 FIXME("(%p) : stub\n", This
);
1489 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST BOOL
*pConstantData
, UINT BoolCount
) {
1490 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1491 if (StartRegister
+ BoolCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
1492 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This
, StartRegister
);
1493 return WINED3DERR_INVALIDCALL
;
1495 if (NULL
== pConstantData
) {
1496 return WINED3DERR_INVALIDCALL
;
1498 FIXME("(%p) : stub\n", This
);
1502 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader
*iface
, UINT StartRegister
, BOOL
*pConstantData
, UINT BoolCount
) {
1503 IWineD3DVertexShaderImpl
* This
= (IWineD3DVertexShaderImpl
*)iface
;
1504 FIXME("(%p) : stub\n", This
);
1510 /* *******************************************
1511 IWineD3DVertexShader IUnknown parts follow
1512 ******************************************* */
1513 HRESULT WINAPI
IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader
*iface
, REFIID riid
, LPVOID
*ppobj
)
1515 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1516 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1517 if (IsEqualGUID(riid
, &IID_IUnknown
)
1518 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
1519 || IsEqualGUID(riid
, &IID_IWineD3DBaseShader
)
1520 || IsEqualGUID(riid
, &IID_IWineD3DVertexShader
)) {
1521 IUnknown_AddRef(iface
);
1526 return E_NOINTERFACE
;
1529 ULONG WINAPI
IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader
*iface
) {
1530 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1531 TRACE("(%p) : AddRef increasing from %ld\n", This
, This
->ref
);
1532 return InterlockedIncrement(&This
->ref
);
1535 ULONG WINAPI
IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader
*iface
) {
1536 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1538 TRACE("(%p) : Releasing from %ld\n", This
, This
->ref
);
1539 ref
= InterlockedDecrement(&This
->ref
);
1541 if (This
->vertexDeclaration
) IWineD3DVertexDeclaration_Release(This
->vertexDeclaration
);
1542 HeapFree(GetProcessHeap(), 0, This
);
1547 /* *******************************************
1548 IWineD3DVertexShader IWineD3DVertexShader parts follow
1549 ******************************************* */
1551 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader
*iface
, IUnknown
** parent
){
1552 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1554 *parent
= This
->parent
;
1555 IUnknown_AddRef(*parent
);
1556 TRACE("(%p) : returning %p\n", This
, *parent
);
1560 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader
* iface
, IWineD3DDevice
**pDevice
){
1561 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1562 IWineD3DDevice_AddRef((IWineD3DDevice
*)This
->wineD3DDevice
);
1563 *pDevice
= (IWineD3DDevice
*)This
->wineD3DDevice
;
1564 TRACE("(%p) returning %p\n", This
, *pDevice
);
1568 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader
* impl
, VOID
* pData
, UINT
* pSizeOfData
) {
1569 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)impl
;
1570 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This
, pData
, pSizeOfData
);
1572 if (NULL
== pData
) {
1573 *pSizeOfData
= This
->baseShader
.functionLength
;
1576 if (*pSizeOfData
< This
->baseShader
.functionLength
) {
1577 *pSizeOfData
= This
->baseShader
.functionLength
;
1578 return WINED3DERR_MOREDATA
;
1580 if (NULL
== This
->baseShader
.function
) { /* no function defined */
1581 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This
, pData
);
1582 (*(DWORD
**) pData
) = NULL
;
1584 if(This
->baseShader
.functionLength
== 0){
1587 TRACE("(%p) : GetFunction copying to %p\n", This
, pData
);
1588 memcpy(pData
, This
->baseShader
.function
, This
->baseShader
.functionLength
);
1593 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
*iface
, CONST DWORD
*pFunction
) {
1594 IWineD3DVertexShaderImpl
*This
=(IWineD3DVertexShaderImpl
*)iface
;
1595 const DWORD
* pToken
= pFunction
;
1596 const SHADER_OPCODE
* curOpcode
= NULL
;
1599 TRACE("(%p) : Parsing programme\n", This
);
1601 /* Initialise vertex input arrays */
1602 This
->namedArrays
= FALSE
;
1603 This
->declaredArrays
= FALSE
;
1604 for (i
= 0; i
< WINED3DSHADERDECLUSAGE_MAX_USAGE
; i
++)
1605 This
->arrayUsageMap
[i
] = -1;
1607 if (NULL
!= pToken
) {
1608 while (D3DVS_END() != *pToken
) {
1609 if (vshader_is_version_token(*pToken
)) { /** version */
1610 vshader_set_version(This
, *pToken
);
1615 if (vshader_is_comment_token(*pToken
)) { /** comment */
1616 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1618 TRACE("//%s\n", (char*)pToken
);
1619 pToken
+= comment_len
;
1620 len
+= comment_len
+ 1;
1623 curOpcode
= shader_get_opcode((IWineD3DBaseShader
*) This
, *pToken
);
1626 if (NULL
== curOpcode
) {
1627 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1628 while (*pToken
& 0x80000000) {
1629 /* unknown current opcode ... */
1630 FIXME("unrecognized opcode: %08lx", *pToken
);
1637 if (curOpcode
->opcode
== D3DSIO_DCL
) {
1639 DWORD usage
= *pToken
;
1640 DWORD param
= *(pToken
+ 1);
1642 parse_decl_usage(This
, usage
, param
& D3DSP_REGNUM_MASK
);
1643 shader_program_dump_decl_usage(usage
, param
);
1644 shader_dump_ins_modifiers(param
);
1646 vshader_program_dump_vs_param(param
, 0);
1651 if (curOpcode
->opcode
== D3DSIO_DEF
) {
1652 TRACE("def c%lu = ", *pToken
& 0xFF);
1655 TRACE("%f ,", *(float *)pToken
);
1658 TRACE("%f ,", *(float *)pToken
);
1661 TRACE("%f ,", *(float *)pToken
);
1664 TRACE("%f", *(float *)pToken
);
1668 TRACE("%s", curOpcode
->name
);
1669 if (curOpcode
->num_params
> 0) {
1670 shader_dump_ins_modifiers(*pToken
);
1672 vshader_program_dump_vs_param(*pToken
, 0);
1675 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
1677 vshader_program_dump_vs_param(*pToken
, 1);
1686 This
->baseShader
.functionLength
= (len
+ 1) * sizeof(DWORD
);
1688 This
->baseShader
.functionLength
= 1; /* no Function defined use fixed function vertex processing */
1691 /* Handy for debugging using numbered arrays instead of named arrays */
1693 /* TODO: using numbered arrays for software shaders makes things easier */
1694 This
->declaredArrays
= TRUE
;
1697 /* named arrays and declared arrays are mutually exclusive */
1698 if (This
->declaredArrays
)
1699 This
->namedArrays
= FALSE
;
1701 /* Generate HW shader in needed */
1702 if (NULL
!= pFunction
&& wined3d_settings
.vs_mode
== VS_HW
) {
1704 IWineD3DVertexShaderImpl_GenerateShader(iface
, pFunction
);
1708 /* copy the function ... because it will certainly be released by application */
1709 if (NULL
!= pFunction
) {
1710 This
->baseShader
.function
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->baseShader
.functionLength
);
1711 memcpy((void *)This
->baseShader
.function
, pFunction
, This
->baseShader
.functionLength
);
1713 This
->baseShader
.function
= NULL
;
1718 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl
=
1720 /*** IUnknown methods ***/
1721 IWineD3DVertexShaderImpl_QueryInterface
,
1722 IWineD3DVertexShaderImpl_AddRef
,
1723 IWineD3DVertexShaderImpl_Release
,
1724 /*** IWineD3DBase methods ***/
1725 IWineD3DVertexShaderImpl_GetParent
,
1726 /*** IWineD3DBaseShader methods ***/
1727 IWineD3DVertexShaderImpl_SetFunction
,
1728 /*** IWineD3DVertexShader methods ***/
1729 IWineD3DVertexShaderImpl_GetDevice
,
1730 IWineD3DVertexShaderImpl_GetFunction