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);
479 * log, exp, frc, m*x* seems to be macros ins ... to see
481 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
484 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, vshader_hw_map2gl, 0, 0},
485 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, 0, 0},
486 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, 0, 0},
487 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, 0, 0},
488 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, 0, 0},
489 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, 0, 0},
490 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, 0, 0},
491 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, 0, 0},
492 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, 0, 0},
493 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, 0, 0},
494 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, 0, 0},
495 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, 0, 0},
496 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, 0, 0},
497 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, 0, 0},
498 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, 0, 0},
499 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, 0, 0},
500 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, 0, 0},
501 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, 0, 0},
502 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, 0, 0},
503 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, 0, 0},
504 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, 0, 0},
505 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, vshader_hw_map2gl, 0, 0},
506 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, 0, 0},
507 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, 0, 0},
508 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, 0, 0},
509 /* TODO: sng can possibly be performed a s
512 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, 0, 0},
513 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
516 MUL vec.xyz, vec, tmp;
517 but I think this is better because it accounts for w properly.
523 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, NULL, 0, 0},
524 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, NULL, 0, 0},
527 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, NULL, 0, 0},
528 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, NULL, 0, 0},
529 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, NULL, 0, 0},
530 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, NULL, 0, 0},
531 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, NULL, 0, 0},
533 /* Declare registers */
534 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, NULL, 0, 0},
536 /* Constant definitions */
537 {D3DSIO_DEF, "def", NULL, 5, vshader_def, NULL, 0, 0},
538 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, 0, 0},
539 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, NULL, 0, 0},
541 /* Flow control - requires GLSL or software shaders */
542 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, 0, 0},
543 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, 0, 0},
544 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, 0, 0},
545 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, 0, 0},
546 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, 0, 0},
547 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, 0, 0},
548 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, 0, 0},
549 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, 0, 0},
550 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, 0, 0},
551 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, 0, 0},
552 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, 0, 0},
553 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, 0, 0},
554 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, 0, 0},
555 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, 0, 0},
556 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, 0, 0},
558 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, 0, 0},
559 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, NULL, 0, 0},
560 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, 0, 0},
561 {0, NULL, NULL, 0, NULL, 0, 0}
564 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
565 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
566 static const char swizzle_reg_chars[] = "xyzw";
568 DWORD reg = param & D3DSP_REGNUM_MASK;
569 DWORD regtype = shader_get_regtype(param);
571 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
581 TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
583 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
587 TRACE("%s", rastout_reg_names[reg]);
592 case D3DSPR_TEXCRDOUT:
595 case D3DSPR_CONSTINT:
596 TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
598 case D3DSPR_CONSTBOOL:
599 TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
605 TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
611 FIXME("Unknown %lu reg %lu\n",regtype, reg);
616 /** operand output */
617 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
618 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
619 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
620 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
621 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
625 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
626 DWORD swizzle_x = swizzle & 0x03;
627 DWORD swizzle_y = (swizzle >> 2) & 0x03;
628 DWORD swizzle_z = (swizzle >> 4) & 0x03;
629 DWORD swizzle_w = (swizzle >> 6) & 0x03;
631 * swizzle bits fields:
634 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
635 if (swizzle_x == swizzle_y &&
636 swizzle_x == swizzle_z &&
637 swizzle_x == swizzle_w) {
638 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
641 swizzle_reg_chars[swizzle_x],
642 swizzle_reg_chars[swizzle_y],
643 swizzle_reg_chars[swizzle_z],
644 swizzle_reg_chars[swizzle_w]);
650 inline static void vshader_program_dump_decl_usage(
651 IWineD3DVertexShaderImpl *This, DWORD decl, DWORD param) {
652 DWORD regtype = shader_get_regtype(param);
656 if (regtype == D3DSPR_SAMPLER) {
657 DWORD ttype = decl & D3DSP_TEXTURETYPE_MASK;
660 case D3DSTT_2D: TRACE("2d "); break;
661 case D3DSTT_CUBE: TRACE("cube "); break;
662 case D3DSTT_VOLUME: TRACE("volume "); break;
663 default: TRACE("unknown_ttype(%08lx) ", ttype);
668 DWORD usage = decl & D3DSP_DCL_USAGE_MASK;
669 DWORD idx = (decl & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
672 case D3DDECLUSAGE_POSITION:
673 TRACE("%s%ld ", "position", idx);
675 case D3DDECLUSAGE_BLENDINDICES:
676 TRACE("%s ", "blend");
678 case D3DDECLUSAGE_BLENDWEIGHT:
679 TRACE("%s ", "weight");
681 case D3DDECLUSAGE_NORMAL:
682 TRACE("%s%ld ", "normal", idx);
684 case D3DDECLUSAGE_PSIZE:
685 TRACE("%s ", "psize");
687 case D3DDECLUSAGE_COLOR:
689 TRACE("%s ", "color");
691 TRACE("%s ", "specular");
694 case D3DDECLUSAGE_TEXCOORD:
695 TRACE("%s%ld ", "texture", idx);
697 case D3DDECLUSAGE_TANGENT:
698 TRACE("%s ", "tangent");
700 case D3DDECLUSAGE_BINORMAL:
701 TRACE("%s ", "binormal");
703 case D3DDECLUSAGE_TESSFACTOR:
704 TRACE("%s ", "tessfactor");
706 case D3DDECLUSAGE_POSITIONT:
707 TRACE("%s%ld ", "positionT", idx);
709 case D3DDECLUSAGE_FOG:
712 case D3DDECLUSAGE_DEPTH:
713 TRACE("%s ", "depth");
715 case D3DDECLUSAGE_SAMPLE:
716 TRACE("%s ", "sample");
719 FIXME("Unrecognised dcl %08lx", usage);
724 inline static BOOL vshader_is_version_token(DWORD token) {
725 return 0xFFFE0000 == (token & 0xFFFE0000);
728 inline static BOOL vshader_is_comment_token(DWORD token) {
729 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
732 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
733 /** operand output */
734 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
736 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
737 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
738 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
739 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
743 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
744 static const char swizzle_reg_chars_color_fix[] = "zyxw";
745 static const char swizzle_reg_chars[] = "xyzw";
746 const char* swizzle_regs = NULL;
750 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
751 DWORD swizzle_x = swizzle & 0x03;
752 DWORD swizzle_y = (swizzle >> 2) & 0x03;
753 DWORD swizzle_z = (swizzle >> 4) & 0x03;
754 DWORD swizzle_w = (swizzle >> 6) & 0x03;
757 swizzle_regs = swizzle_reg_chars_color_fix;
759 swizzle_regs = swizzle_reg_chars;
763 * swizzle bits fields:
766 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
768 sprintf(tmpReg, ".%c%c%c%c",
769 swizzle_regs[swizzle_x],
770 swizzle_regs[swizzle_y],
771 swizzle_regs[swizzle_z],
772 swizzle_regs[swizzle_w]);
773 strcat(hwLine, tmpReg);
777 if (swizzle_x == swizzle_y &&
778 swizzle_x == swizzle_z &&
779 swizzle_x == swizzle_w)
781 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
782 strcat(hwLine, tmpReg);
784 sprintf(tmpReg, ".%c%c%c%c",
785 swizzle_regs[swizzle_x],
786 swizzle_regs[swizzle_y],
787 swizzle_regs[swizzle_z],
788 swizzle_regs[swizzle_w]);
789 strcat(hwLine, tmpReg);
793 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
794 /* oPos, oFog and oPts in D3D */
795 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
797 DWORD reg = param & D3DSP_REGNUM_MASK;
798 DWORD regtype = shader_get_regtype(param);
800 BOOL is_color = FALSE;
802 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
803 strcat(hwLine, " -");
810 sprintf(tmpReg, "T%lu", reg);
811 strcat(hwLine, tmpReg);
814 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
815 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
818 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
819 if (This->namedArrays) {
820 sprintf(tmpReg, "namedVertex%lu", reg);
822 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
823 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
825 strcat(hwLine, tmpReg);
828 /* FIXME: some constants are named so we need a constants map*/
829 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
830 if (param & D3DVS_ADDRMODE_RELATIVE) {
831 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
833 sprintf(tmpReg, "const%lu", reg);
835 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
837 strcat(hwLine, tmpReg);
839 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
840 sprintf(tmpReg, "A%lu", reg);
841 strcat(hwLine, tmpReg);
844 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
845 strcat(hwLine, tmpReg);
849 strcat(hwLine, "result.color.primary");
851 strcat(hwLine, "result.color.secondary");
854 case D3DSPR_TEXCRDOUT:
855 sprintf(tmpReg, "result.texcoord[%lu]", reg);
856 strcat(hwLine, tmpReg);
859 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
864 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
866 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
870 DWORD MacroExpansion[4*4];
872 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
877 switch(macro_opcode) {
901 for (i = 0; i < nComponents; i++) {
902 MacroExpansion[i*4+0] = opcode;
903 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
904 MacroExpansion[i*4+2] = *(args+1);
905 MacroExpansion[i*4+3] = (*(args+2))+i;
910 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
912 switch(usage & 0xFFFF) {
913 case D3DDECLUSAGE_POSITION:
914 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
915 TRACE("Setting position to %d\n", arrayNo);
916 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
917 This->namedArrays = TRUE;
919 /* TODO: position indexes go from 0-8!!*/
920 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
921 /* robots uses positions up to 8, the position arrays are just packed.*/
922 if ((usage & 0xF0000) >> 16 > 1) {
923 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
925 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
926 This->declaredArrays = TRUE;
929 case D3DDECLUSAGE_BLENDINDICES:
930 /* not supported by openGL */
931 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
932 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
933 This->declaredArrays = TRUE;
934 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
936 case D3DDECLUSAGE_BLENDWEIGHT:
937 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
938 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
939 This->namedArrays = TRUE;
940 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
942 case D3DDECLUSAGE_NORMAL:
943 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
944 TRACE("Setting normal to %d\n", arrayNo);
945 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
946 This->namedArrays = TRUE;
948 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
949 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
950 This->declaredArrays = TRUE;
953 case D3DDECLUSAGE_PSIZE:
954 TRACE("Setting PSIZE to %d\n", arrayNo);
955 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
956 This->namedArrays = TRUE;
957 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
959 case D3DDECLUSAGE_COLOR:
960 if((usage & 0xF0000) >> 16 == 0) {
961 TRACE("Setting DIFFUSE to %d\n", arrayNo);
962 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
963 This->namedArrays = TRUE;
965 TRACE("Setting SPECULAR to %d\n", arrayNo);
966 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
967 This->namedArrays = TRUE;
970 case D3DDECLUSAGE_TEXCOORD:
971 This->namedArrays = TRUE;
972 /* only 7 texture coords have been designed for, so run a quick sanity check */
973 if ((usage & 0xF0000) >> 16 > 7) {
974 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
976 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
977 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
980 /* The following aren't supported by openGL,
981 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
982 this should be caught in the first pass */
983 case D3DDECLUSAGE_TANGENT:
984 TRACE("Setting TANGENT to %d\n", arrayNo);
985 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
986 This->declaredArrays = TRUE;
988 case D3DDECLUSAGE_BINORMAL:
989 TRACE("Setting BINORMAL to %d\n", arrayNo);
990 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
991 This->declaredArrays = TRUE;
993 case D3DDECLUSAGE_TESSFACTOR:
994 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
995 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
996 This->declaredArrays = TRUE;
998 case D3DDECLUSAGE_POSITIONT:
999 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1000 FIXME("Setting positiont to %d\n", arrayNo);
1001 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1002 This->namedArrays = TRUE;
1004 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1005 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1006 This->declaredArrays = TRUE;
1007 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1010 case D3DDECLUSAGE_FOG:
1011 /* supported by OpenGL */
1012 TRACE("Setting FOG to %d\n", arrayNo);
1013 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1014 This->namedArrays = TRUE;
1016 case D3DDECLUSAGE_DEPTH:
1017 TRACE("Setting DEPTH to %d\n", arrayNo);
1018 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1019 This->declaredArrays = TRUE;
1021 case D3DDECLUSAGE_SAMPLE:
1022 TRACE("Setting SAMPLE to %d\n", arrayNo);
1023 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1024 This->declaredArrays = TRUE;
1027 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1031 void vshader_set_version(
1032 IWineD3DVertexShaderImpl *This,
1035 DWORD major = (version >> 8) & 0x0F;
1036 DWORD minor = version & 0x0F;
1038 This->baseShader.hex_version = version;
1039 This->baseShader.version = major * 10 + minor;
1040 TRACE("vs_%lu_%lu\n", major, minor);
1042 This->baseShader.limits.texture = 0;
1044 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
1045 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
1047 switch (This->baseShader.version) {
1049 case 11: This->baseShader.limits.temporary = 12;
1050 This->baseShader.limits.constant_bool = 0;
1051 This->baseShader.limits.constant_int = 0;
1052 This->baseShader.limits.address = 1;
1056 case 21: This->baseShader.limits.temporary = 12;
1057 This->baseShader.limits.constant_bool = 16;
1058 This->baseShader.limits.constant_int = 16;
1059 This->baseShader.limits.address = 1;
1062 case 30: This->baseShader.limits.temporary = 32;
1063 This->baseShader.limits.constant_bool = 32;
1064 This->baseShader.limits.constant_int = 32;
1065 This->baseShader.limits.address = 1;
1068 default: This->baseShader.limits.temporary = 12;
1069 This->baseShader.limits.constant_bool = 0;
1070 This->baseShader.limits.constant_int = 0;
1071 This->baseShader.limits.address = 1;
1072 FIXME("Unrecognized vertex shader version %lu!\n", version);
1076 /* Map the opcode 1-to-1 to the GL code */
1077 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
1079 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
1080 CONST SHADER_OPCODE* curOpcode = arg->opcode;
1081 SHADER_BUFFER* buffer = arg->buffer;
1082 DWORD dst = arg->dst;
1083 DWORD* src = arg->src;
1085 DWORD dst_regtype = shader_get_regtype(dst);
1089 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
1090 strcpy(tmpLine, "ARL");
1092 strcpy(tmpLine, curOpcode->glname);
1094 if (curOpcode->num_params > 0) {
1095 vshader_program_add_param(This, dst, FALSE, tmpLine);
1096 for (i = 1; i < curOpcode->num_params; ++i) {
1097 strcat(tmpLine, ",");
1098 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
1101 shader_addline(buffer, "%s;\n", tmpLine);
1105 * Function parser ...
1108 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1109 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1110 const DWORD* pToken = pFunction;
1111 const DWORD* pSavedToken = NULL;
1112 const SHADER_OPCODE* curOpcode = NULL;
1115 SHADER_BUFFER buffer;
1117 DWORD addressUsed, tempsUsed;
1119 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1120 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1121 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1122 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1123 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1124 This->fixupVertexBufferSize = PGMSIZE;
1125 This->fixupVertexBuffer[0] = 0;
1127 buffer.buffer = This->device->fixupVertexBuffer;
1129 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1133 /* First pass: figure out which temporary and texture registers are used */
1134 shader_get_registers_used((IWineD3DBaseShader*) This, pToken, &tempsUsed, &addressUsed);
1135 TRACE("Address registers used: %#lx, Temp registers used %#lx\n", addressUsed, tempsUsed);
1137 /* TODO: check register usage against GL/Directx limits, and fail if they're exceeded
1138 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1139 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1142 /* Mesa supports only 95 constants */
1143 if (GL_VEND(MESA) || GL_VEND(WINE))
1144 This->baseShader.limits.constant_float =
1145 min(95, This->baseShader.limits.constant_float);
1147 /* FIXME: if jumps are used, use GLSL, else use ARB_vertex_program */
1148 shader_addline(&buffer, "!!ARBvp1.0\n");
1150 /* Pre-declare registers */
1151 for (i = 0; i < This->baseShader.limits.temporary; i++) {
1152 if (tempsUsed & (1 << i))
1153 shader_addline(&buffer, "TEMP T%lu;\n", i);
1156 for (i = 0; i < This->baseShader.limits.address; i++) {
1157 if (addressUsed & (1 << i))
1158 shader_addline(&buffer, "ADDRESS A%ld;\n", i);
1161 /* Why do we need to alias those? */
1162 shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1163 This->baseShader.limits.constant_float,
1164 This->baseShader.limits.constant_float - 1);
1166 /** second pass, now generate */
1169 if (NULL != pToken) {
1172 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1173 /* Macro is finished, continue normal path */
1174 pToken = pSavedToken;
1175 if (D3DVS_END() == *pToken)
1179 if (vshader_is_version_token(*pToken)) {
1185 if (vshader_is_comment_token(*pToken)) {
1186 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1188 TRACE("#%s\n", (char*)pToken);
1189 pToken += comment_len;
1193 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1195 if (NULL == curOpcode) {
1196 /* unknown current opcode ... (shouldn't be any!) */
1197 while (*pToken & 0x80000000) {
1198 FIXME("unrecognized opcode: %08lx\n", *pToken);
1201 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1202 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1204 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1205 pToken += curOpcode->num_params;
1207 } else if (D3DSIO_DEF == curOpcode->opcode) {
1209 /* Handle definitions here, they don't fit well with the
1210 * other instructions below [for now ] */
1212 shader_addline(&buffer,
1213 "PARAM const%lu = { %f, %f, %f, %f };\n", *pToken & 0xFF,
1214 *(float *) (pToken + 1),
1215 *(float *) (pToken + 2),
1216 *(float *) (pToken + 3),
1217 *(float *) (pToken + 4));
1219 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1223 } else if (D3DSIO_DCL == curOpcode->opcode) {
1225 /* Handle declarations here, they don't fit well with the
1226 * other instructions below [for now ] */
1228 if (This->namedArrays) {
1229 const char* attribName = "undefined";
1230 switch(*pToken & 0xFFFF) {
1231 case D3DDECLUSAGE_POSITION:
1232 attribName = "vertex.position";
1234 case D3DDECLUSAGE_BLENDINDICES:
1235 /* not supported by openGL */
1236 attribName = "vertex.blend";
1238 case D3DDECLUSAGE_BLENDWEIGHT:
1239 attribName = "vertex.weight";
1241 case D3DDECLUSAGE_NORMAL:
1242 attribName = "vertex.normal";
1244 case D3DDECLUSAGE_PSIZE:
1245 attribName = "vertex.psize";
1247 case D3DDECLUSAGE_COLOR:
1248 if((*pToken & 0xF0000) >> 16 == 0) {
1249 attribName = "vertex.color";
1251 attribName = "vertex.color.secondary";
1254 case D3DDECLUSAGE_TEXCOORD:
1258 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1259 attribName = tmpChar;
1262 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1263 case D3DDECLUSAGE_TANGENT:
1264 attribName = "vertex.tangent";
1266 case D3DDECLUSAGE_BINORMAL:
1267 attribName = "vertex.binormal";
1269 case D3DDECLUSAGE_TESSFACTOR:
1270 attribName = "vertex.tessfactor";
1272 case D3DDECLUSAGE_POSITIONT:
1273 attribName = "vertex.possitionT";
1275 case D3DDECLUSAGE_FOG:
1276 attribName = "vertex.fogcoord";
1278 case D3DDECLUSAGE_DEPTH:
1279 attribName = "vertex.depth";
1281 case D3DDECLUSAGE_SAMPLE:
1282 attribName = "vertex.sample";
1285 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1289 sprintf(tmpLine, "ATTRIB ");
1290 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1291 if (This->namedArrays)
1292 shader_addline(&buffer, "%s = %s;\n", tmpLine, attribName);
1295 /* eat the token so it doesn't generate a warning */
1301 /* If a generator function is set, use it */
1302 } else if (curOpcode->hw_fct != NULL) {
1304 SHADER_OPCODE_ARG hw_arg;
1306 hw_arg.shader = (IWineD3DBaseShader*) This;
1307 hw_arg.opcode = curOpcode;
1308 hw_arg.buffer = &buffer;
1309 if (curOpcode->num_params > 0) {
1310 hw_arg.dst = *pToken;
1312 /* FIXME: this does not account for relative address tokens */
1313 for (i = 1; i < curOpcode->num_params; i++)
1314 hw_arg.src[i-1] = *(pToken + i);
1317 curOpcode->hw_fct(&hw_arg);
1318 pToken += curOpcode->num_params;
1322 switch (curOpcode->opcode) {
1330 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1331 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1332 /* Save point to next instruction */
1333 pSavedToken = pToken + 3;
1334 /* Execute expanded macro */
1335 pToken = MacroExpansion;
1339 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1340 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1342 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1345 pToken += curOpcode->num_params;
1349 shader_addline(&buffer, "END\n");
1352 /* finally null terminate the buffer */
1353 buffer.buffer[buffer.bsize] = 0;
1355 /* Check that Vertex Shaders are supported */
1356 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1357 /* Create the hw shader */
1358 /* TODO: change to resource.glObjectHandel or something like that */
1359 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1360 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1361 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1363 /* Create the program and check for errors */
1364 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1365 buffer.bsize, buffer.buffer));
1367 if (glGetError() == GL_INVALID_OPERATION) {
1369 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1370 FIXME("HW VertexShader Error at position %d: %s\n",
1371 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1372 This->baseShader.prgId = -1;
1375 #if 1 /* if were using the data buffer of device then we don't need to free it */
1376 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1380 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1382 * TODO: use the NV_vertex_program (or 1_1) extension
1383 * and specifics vendors (ARB_vertex_program??) variants for it
1388 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1389 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1391 /** Vertex Shader Temporary Registers */
1392 WINED3DSHADERVECTOR R[12];
1393 /*D3DSHADERSCALAR A0;*/
1394 WINED3DSHADERVECTOR A[1];
1395 /** temporary Vector for modifier management */
1396 WINED3DSHADERVECTOR d;
1397 WINED3DSHADERVECTOR s[3];
1399 const DWORD* pToken = This->baseShader.function;
1400 const SHADER_OPCODE* curOpcode = NULL;
1401 /** functions parameters */
1402 WINED3DSHADERVECTOR* p[4];
1403 WINED3DSHADERVECTOR* p_send[4];
1406 /** init temporary register */
1407 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1409 /* vshader_program_parse(vshader); */
1410 #if 0 /* Must not be 1 in cvs */
1412 TRACE_VSVECTOR(This->data->C[0]);
1413 TRACE_VSVECTOR(This->data->C[1]);
1414 TRACE_VSVECTOR(This->data->C[2]);
1415 TRACE_VSVECTOR(This->data->C[3]);
1416 TRACE_VSVECTOR(This->data->C[4]);
1417 TRACE_VSVECTOR(This->data->C[5]);
1418 TRACE_VSVECTOR(This->data->C[6]);
1419 TRACE_VSVECTOR(This->data->C[7]);
1420 TRACE_VSVECTOR(This->data->C[8]);
1421 TRACE_VSVECTOR(This->data->C[64]);
1422 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1423 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1424 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1425 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1426 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1427 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1428 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1429 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1430 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1433 TRACE_VSVECTOR(vshader->data->C[64]);
1434 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1436 /* the first dword is the version tag */
1437 /* TODO: parse it */
1439 if (vshader_is_version_token(*pToken)) { /** version */
1442 while (D3DVS_END() != *pToken) {
1443 if (vshader_is_comment_token(*pToken)) { /** comment */
1444 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1446 pToken += comment_len;
1449 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1451 if (NULL == curOpcode) {
1453 /* unknown current opcode ... */
1454 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1455 while (*pToken & 0x80000000) {
1457 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1459 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1460 vshader_program_dump_vs_param(*pToken, i);
1467 if (curOpcode->num_params > 0) {
1468 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1469 for (i = 0; i < curOpcode->num_params; ++i) {
1470 DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1471 DWORD regtype = shader_get_regtype(pToken[i]);
1475 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1479 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1480 p[i] = &input->V[reg];
1483 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1484 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1486 p[i] = &This->data->C[reg];
1489 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1491 ERR("cannot handle address registers != a0, forcing use of a0\n");
1494 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1497 case D3DSPR_RASTOUT:
1499 case D3DSRO_POSITION:
1500 p[i] = &output->oPos;
1503 p[i] = &output->oFog;
1505 case D3DSRO_POINT_SIZE:
1506 p[i] = &output->oPts;
1510 case D3DSPR_ATTROUT:
1511 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1512 p[i] = &output->oD[reg];
1514 case D3DSPR_TEXCRDOUT:
1515 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1516 p[i] = &output->oT[reg];
1518 /* TODO Decls and defs */
1527 if (i > 0) { /* input reg */
1528 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1529 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1531 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1532 /* TRACE("p[%d] not swizzled\n", i); */
1535 DWORD swizzle_x = swizzle & 0x03;
1536 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1537 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1538 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1539 /* TRACE("p[%d] swizzled\n", i); */
1540 float* tt = (float*) p[i];
1541 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1542 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1543 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1544 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1547 } else { /* output reg */
1548 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1551 p_send[i] = &d; /* to be post-processed for modifiers management */
1557 switch (curOpcode->num_params) {
1559 curOpcode->soft_fct();
1562 curOpcode->soft_fct(p_send[0]);
1565 curOpcode->soft_fct(p_send[0], p_send[1]);
1568 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1571 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1574 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1577 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1580 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1583 /* check if output reg modifier post-process */
1584 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1585 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1586 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1587 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1588 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1591 TRACE_VSVECTOR(output->oPos);
1592 TRACE_VSVECTOR(output->oD[0]);
1593 TRACE_VSVECTOR(output->oD[1]);
1594 TRACE_VSVECTOR(output->oT[0]);
1595 TRACE_VSVECTOR(output->oT[1]);
1596 TRACE_VSVECTOR(R[0]);
1597 TRACE_VSVECTOR(R[1]);
1598 TRACE_VSVECTOR(R[2]);
1599 TRACE_VSVECTOR(R[3]);
1600 TRACE_VSVECTOR(R[4]);
1601 TRACE_VSVECTOR(R[5]);
1604 /* to next opcode token */
1605 pToken += curOpcode->num_params;
1608 TRACE("End of current instruction:\n");
1609 TRACE_VSVECTOR(output->oPos);
1610 TRACE_VSVECTOR(output->oD[0]);
1611 TRACE_VSVECTOR(output->oD[1]);
1612 TRACE_VSVECTOR(output->oT[0]);
1613 TRACE_VSVECTOR(output->oT[1]);
1614 TRACE_VSVECTOR(R[0]);
1615 TRACE_VSVECTOR(R[1]);
1616 TRACE_VSVECTOR(R[2]);
1617 TRACE_VSVECTOR(R[3]);
1618 TRACE_VSVECTOR(R[4]);
1619 TRACE_VSVECTOR(R[5]);
1622 #if 0 /* Must not be 1 in cvs */
1624 TRACE_VSVECTOR(output->oPos);
1625 TRACE_VSVECTOR(output->oD[0]);
1626 TRACE_VSVECTOR(output->oD[1]);
1627 TRACE_VSVECTOR(output->oT[0]);
1628 TRACE_VSVECTOR(output->oT[1]);
1633 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1634 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1635 FIXME("(%p) : stub\n", This);
1639 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1640 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1641 FIXME("(%p) : stub\n", This);
1645 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1646 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1647 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1648 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1649 return WINED3DERR_INVALIDCALL;
1651 if (NULL == pConstantData) {
1652 return WINED3DERR_INVALIDCALL;
1654 FIXME("(%p) : stub\n", This);
1658 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1659 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1660 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1661 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1662 return WINED3DERR_INVALIDCALL;
1664 if (NULL == pConstantData) {
1665 return WINED3DERR_INVALIDCALL;
1667 FIXME("(%p) : stub\n", This);
1671 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1672 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1673 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1674 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1675 return WINED3DERR_INVALIDCALL;
1677 if (NULL == pConstantData) {
1678 return WINED3DERR_INVALIDCALL;
1680 FIXME("(%p) : stub\n", This);
1684 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1685 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1686 FIXME("(%p) : stub\n", This);
1692 /* *******************************************
1693 IWineD3DVertexShader IUnknown parts follow
1694 ******************************************* */
1695 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1697 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1698 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1699 if (IsEqualGUID(riid, &IID_IUnknown)
1700 || IsEqualGUID(riid, &IID_IWineD3DBase)
1701 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1702 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1703 IUnknown_AddRef(iface);
1708 return E_NOINTERFACE;
1711 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1712 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1713 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1714 return InterlockedIncrement(&This->ref);
1717 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1718 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1720 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1721 ref = InterlockedDecrement(&This->ref);
1723 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1724 HeapFree(GetProcessHeap(), 0, This);
1729 /* *******************************************
1730 IWineD3DVertexShader IWineD3DVertexShader parts follow
1731 ******************************************* */
1733 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1734 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1736 *parent = This->parent;
1737 IUnknown_AddRef(*parent);
1738 TRACE("(%p) : returning %p\n", This, *parent);
1742 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1743 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1744 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1745 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1746 TRACE("(%p) returning %p\n", This, *pDevice);
1750 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1751 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1752 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1754 if (NULL == pData) {
1755 *pSizeOfData = This->baseShader.functionLength;
1758 if (*pSizeOfData < This->baseShader.functionLength) {
1759 *pSizeOfData = This->baseShader.functionLength;
1760 return WINED3DERR_MOREDATA;
1762 if (NULL == This->baseShader.function) { /* no function defined */
1763 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1764 (*(DWORD **) pData) = NULL;
1766 if(This->baseShader.functionLength == 0){
1769 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1770 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1775 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1776 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1777 const DWORD* pToken = pFunction;
1778 const SHADER_OPCODE* curOpcode = NULL;
1781 TRACE("(%p) : Parsing programme\n", This);
1783 /* Initialise vertex input arrays */
1784 This->namedArrays = FALSE;
1785 This->declaredArrays = FALSE;
1786 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1787 This->arrayUsageMap[i] = -1;
1789 if (NULL != pToken) {
1790 while (D3DVS_END() != *pToken) {
1791 if (vshader_is_version_token(*pToken)) { /** version */
1792 vshader_set_version(This, *pToken);
1797 if (vshader_is_comment_token(*pToken)) { /** comment */
1798 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1800 TRACE("//%s\n", (char*)pToken);
1801 pToken += comment_len;
1802 len += comment_len + 1;
1805 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1808 if (NULL == curOpcode) {
1809 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1810 while (*pToken & 0x80000000) {
1811 /* unknown current opcode ... */
1812 FIXME("unrecognized opcode: %08lx", *pToken);
1819 if (curOpcode->opcode == D3DSIO_DCL) {
1821 DWORD usage = *pToken;
1822 DWORD param = *(pToken + 1);
1824 parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1825 vshader_program_dump_decl_usage(This, usage, param);
1826 vshader_program_dump_vs_param(param, 0);
1831 if (curOpcode->opcode == D3DSIO_DEF) {
1832 TRACE("def c%lu = ", *pToken & 0xFF);
1835 TRACE("%f ,", *(float *)pToken);
1838 TRACE("%f ,", *(float *)pToken);
1841 TRACE("%f ,", *(float *)pToken);
1844 TRACE("%f", *(float *)pToken);
1848 TRACE("%s ", curOpcode->name);
1849 if (curOpcode->num_params > 0) {
1850 vshader_program_dump_vs_param(*pToken, 0);
1853 for (i = 1; i < curOpcode->num_params; ++i) {
1855 vshader_program_dump_vs_param(*pToken, 1);
1864 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1866 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1869 /* Handy for debugging using numbered arrays instead of named arrays */
1871 /* TODO: using numbered arrays for software shaders makes things easier */
1872 This->declaredArrays = TRUE;
1875 /* named arrays and declared arrays are mutually exclusive */
1876 if (This->declaredArrays)
1877 This->namedArrays = FALSE;
1879 /* Generate HW shader in needed */
1880 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1882 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
1886 /* copy the function ... because it will certainly be released by application */
1887 if (NULL != pFunction) {
1888 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1889 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1891 This->baseShader.function = NULL;
1896 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1898 /*** IUnknown methods ***/
1899 IWineD3DVertexShaderImpl_QueryInterface,
1900 IWineD3DVertexShaderImpl_AddRef,
1901 IWineD3DVertexShaderImpl_Release,
1902 /*** IWineD3DBase methods ***/
1903 IWineD3DVertexShaderImpl_GetParent,
1904 /*** IWineD3DBaseShader methods ***/
1905 IWineD3DVertexShaderImpl_SetFunction,
1906 /*** IWineD3DVertexShader methods ***/
1907 IWineD3DVertexShaderImpl_GetDevice,
1908 IWineD3DVertexShaderImpl_GetFunction