Bug Summary

File:Source/Core/VideoCommon/Src/VertexShaderGen.cpp
Location:line 106, column 5
Description:Value stored to 'ptr' is never read

Annotated Source Code

1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <math.h>
6#include <locale.h>
7
8#include "NativeVertexFormat.h"
9
10#include "BPMemory.h"
11#include "CPMemory.h"
12#include "LightingShaderGen.h"
13#include "VertexShaderGen.h"
14#include "VideoConfig.h"
15
16// Mash together all the inputs that contribute to the code of a generated vertex shader into
17// a unique identifier, basically containing all the bits. Yup, it's a lot ....
18void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components)
19{
20 memset(uid->values, 0, sizeof(uid->values));
21 uid->values[0] = components |
22 (xfregs.numTexGen.numTexGens << 23) |
23 (xfregs.numChan.numColorChans << 27) |
24 (xfregs.dualTexTrans.enabled << 29);
25
26 // TODO: If pixel lighting is enabled, do we even have to bother about storing lighting related registers here?
27 GetLightingShaderId(&uid->values[1]);
28
29 uid->values[2] |= (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) << 31;
30 u32 *pcurvalue = &uid->values[3];
31 for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
32 {
33 TexMtxInfo tinfo = xfregs.texMtxInfo[i];
34 if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP1)
35 tinfo.hex &= 0x7ff;
36 if (tinfo.texgentype != XF_TEXGEN_REGULAR0)
37 tinfo.projection = 0;
38
39 u32 val = ((tinfo.hex >> 1) & 0x1ffff);
40 if (xfregs.dualTexTrans.enabled && tinfo.texgentype == XF_TEXGEN_REGULAR0)
41 {
42 // rewrite normalization and post index
43 val |= ((u32)xfregs.postMtxInfo[i].index << 17) | ((u32)xfregs.postMtxInfo[i].normalize << 23);
44 }
45
46 switch (i & 3)
47 {
48 case 0: pcurvalue[0] |= val; break;
49 case 1: pcurvalue[0] |= val << 24; pcurvalue[1] = val >> 8; ++pcurvalue; break;
50 case 2: pcurvalue[0] |= val << 16; pcurvalue[1] = val >> 16; ++pcurvalue; break;
51 case 3: pcurvalue[0] |= val << 8; ++pcurvalue; break;
52 }
53 }
54}
55
56void GetSafeVertexShaderId(VERTEXSHADERUIDSAFE *uid, u32 components)
57{
58 // Just store all used registers here without caring whether we need all bits or less.
59 memset(uid->values, 0, sizeof(uid->values));
60 u32* ptr = uid->values;
61 *ptr++ = components;
62 *ptr++ = xfregs.numTexGen.hex;
63 *ptr++ = xfregs.numChan.hex;
64 *ptr++ = xfregs.dualTexTrans.hex;
65
66 for (int i = 0; i < 2; ++i)
67 {
68 *ptr++ = xfregs.color[i].hex;
69 *ptr++ = xfregs.alpha[i].hex;
70 }
71
72 *ptr++ = g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting;
73
74 for (unsigned int i = 0; i < 8; ++i)
75 {
76 *ptr++ = xfregs.texMtxInfo[i].hex;
77 *ptr++ = xfregs.postMtxInfo[i].hex;
78 }
79 _assert_((ptr - uid->values) == uid->GetNumValues()){};
80}
81
82
83void ValidateVertexShaderIDs(API_TYPE api, VERTEXSHADERUIDSAFE old_id, const std::string& old_code, u32 components)
84{
85 if (!g_ActiveConfig.bEnableShaderDebugging)
86 return;
87
88 VERTEXSHADERUIDSAFE new_id;
89 GetSafeVertexShaderId(&new_id, components);
90
91 if (!(old_id == new_id))
92 {
93 std::string new_code(GenerateVertexShaderCode(components, api));
94 if (old_code != new_code)
95 {
96 _assert_(old_id.GetNumValues() == new_id.GetNumValues()){};
97
98 char msg[8192];
99 char* ptr = msg;
100 ptr += sprintf(ptr, "Vertex shader IDs matched but unique IDs did not!\nUnique IDs (old <-> new):\n");
101 const int N = new_id.GetNumValues();
102 for (int i = 0; i < N/2; ++i)
103 ptr += sprintf(ptr, "%02d, %08X %08X | %08X %08X\n", 2*i, old_id.values[2*i], old_id.values[2*i+1],
104 new_id.values[2*i], new_id.values[2*i+1]);
105 if (N % 2)
106 ptr += sprintf(ptr, "%02d, %08X | %08X\n", N-1, old_id.values[N-1], new_id.values[N-1]);
Value stored to 'ptr' is never read
107
108 static int num_failures = 0;
109 char szTemp[MAX_PATH4096];
110 sprintf(szTemp, "%svsuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
111 std::ofstream file;
112 OpenFStream(file, szTemp, std::ios_base::out);
113 file << msg;
114 file << "\n\nOld shader code:\n" << old_code;
115 file << "\n\nNew shader code:\n" << new_code;
116 file.close();
117
118 PanicAlert("Unique pixel shader ID mismatch!\n\nReport this to the devs, along with the contents of %s.", szTemp)MsgAlert(false, WARNING, "Unique pixel shader ID mismatch!\n\nReport this to the devs, along with the contents of %s."
, szTemp)
;
119 }
120 }
121}
122
123
124static char text[16384];
125
126#define WRITEp+=sprintf p+=sprintf
127
128char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE ApiType)
129{
130
131 // "centroid" attribute is only supported by D3D11
132 const char* optCentroid = (ApiType == API_D3D11 ? "centroid" : "");
133
134 // GLSL makes this ugly
135 // TODO: Make pretty
136 WRITEp+=sprintf(p, "struct VS_OUTPUT {\n");
137 WRITEp+=sprintf(p, " %s float4 pos %s POSITION;\n", optCentroid, ApiType == API_OPENGL ? ";//" : ":");
138 WRITEp+=sprintf(p, " %s float4 colors_0 %s COLOR0;\n", optCentroid, ApiType == API_OPENGL ? ";//" : ":");
139 WRITEp+=sprintf(p, " %s float4 colors_1 %s COLOR1;\n", optCentroid, ApiType == API_OPENGL ? ";//" : ":");
140
141 if (xfregs.numTexGen.numTexGens < 7)
142 {
143 for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
144 WRITEp+=sprintf(p, " %s float3 tex%d %s TEXCOORD%d;\n", optCentroid, i, ApiType == API_OPENGL ? ";//" : ":", i);
145
146 WRITEp+=sprintf(p, " %s float4 clipPos %s TEXCOORD%d;\n", optCentroid, ApiType == API_OPENGL ? ";//" : ":", xfregs.numTexGen.numTexGens);
147
148 if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
149 WRITEp+=sprintf(p, " %s float4 Normal %s TEXCOORD%d;\n", optCentroid, ApiType == API_OPENGL ? ";//" : ":", xfregs.numTexGen.numTexGens + 1);
150 }
151 else
152 {
153 // clip position is in w of first 4 texcoords
154 if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
155 {
156 for (int i = 0; i < 8; ++i)
157 WRITEp+=sprintf(p, " %s float4 tex%d %s TEXCOORD%d;\n", optCentroid, i, ApiType == API_OPENGL? ";//" : ":", i);
158 }
159 else
160 {
161 for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
162 WRITEp+=sprintf(p, " %s float%d tex%d %s TEXCOORD%d;\n", optCentroid, i < 4 ? 4 : 3 , i, ApiType == API_OPENGL ? ";//" : ":", i);
163 }
164 }
165 WRITEp+=sprintf(p, "};\n");
166
167 return p;
168}
169
170extern const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num);
171extern const char *WriteLocation(API_TYPE ApiType);
172
173const char *GenerateVertexShaderCode(u32 components, API_TYPE ApiType)
174{
175 setlocale(LC_NUMERIC1, "C"); // Reset locale for compilation
176 text[sizeof(text) - 1] = 0x7C; // canary
177
178 _assert_(bpmem.genMode.numtexgens == xfregs.numTexGen.numTexGens){};
179 _assert_(bpmem.genMode.numcolchans == xfregs.numChan.numColorChans){};
180
181 bool is_d3d = (ApiType & API_D3D9 || ApiType == API_D3D11);
182 u32 lightMask = 0;
183 if (xfregs.numChan.numColorChans > 0)
184 lightMask |= xfregs.color[0].GetFullLightMask() | xfregs.alpha[0].GetFullLightMask();
185 if (xfregs.numChan.numColorChans > 1)
186 lightMask |= xfregs.color[1].GetFullLightMask() | xfregs.alpha[1].GetFullLightMask();
187
188 char *p = text;
189 WRITEp+=sprintf(p, "//Vertex Shader: comp:%x, \n", components);
190
191 // uniforms
192 if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
193 WRITEp+=sprintf(p, "layout(std140) uniform VSBlock {\n");
194
195 WRITEp+=sprintf(p, "%sfloat4 " I_POSNORMALMATRIX"cpnmtx""[6] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_POSNORMALMATRIX0));
196 WRITEp+=sprintf(p, "%sfloat4 " I_PROJECTION"cproj""[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PROJECTION(0 + 6)));
197 WRITEp+=sprintf(p, "%sfloat4 " I_MATERIALS"cmtrl""[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_MATERIALS((0 + 6) + 4)));
198 WRITEp+=sprintf(p, "%sfloat4 " I_LIGHTS"clights""[40] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_LIGHTS(((0 + 6) + 4) + 4)));
199 WRITEp+=sprintf(p, "%sfloat4 " I_TEXMATRICES"ctexmtx""[24] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_TEXMATRICES((((0 + 6) + 4) + 4) + 40))); // also using tex matrices
200 WRITEp+=sprintf(p, "%sfloat4 " I_TRANSFORMMATRICES"ctrmtx""[64] %s;\n", WriteLocation(ApiType),WriteRegister(ApiType, "c", C_TRANSFORMMATRICES(((((0 + 6) + 4) + 4) + 40) + 24)));
201 WRITEp+=sprintf(p, "%sfloat4 " I_NORMALMATRICES"cnmtx""[32] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_NORMALMATRICES((((((0 + 6) + 4) + 4) + 40) + 24) + 64)));
202 WRITEp+=sprintf(p, "%sfloat4 " I_POSTTRANSFORMMATRICES"cpostmtx""[64] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_POSTTRANSFORMMATRICES(((((((0 + 6) + 4) + 4) + 40) + 24) + 64) + 32)));
203 WRITEp+=sprintf(p, "%sfloat4 " I_DEPTHPARAMS"cDepth"" %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_DEPTHPARAMS((((((((0 + 6) + 4) + 4) + 40) + 24) + 64) + 32) + 64)));
204
205 if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
206 WRITEp+=sprintf(p, "};\n");
207
208 p = GenerateVSOutputStruct(p, components, ApiType);
209
210 if(ApiType == API_OPENGL)
211 {
212 WRITEp+=sprintf(p, "ATTRIN float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB0);
213 if (components & VB_HAS_POSMTXIDX)
214 WRITEp+=sprintf(p, "ATTRIN float fposmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB1);
215 if (components & VB_HAS_NRM0)
216 WRITEp+=sprintf(p, "ATTRIN float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB2);
217 if (components & VB_HAS_NRM1)
218 WRITEp+=sprintf(p, "ATTRIN float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB3);
219 if (components & VB_HAS_NRM2)
220 WRITEp+=sprintf(p, "ATTRIN float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB4);
221
222 if (components & VB_HAS_COL0)
223 WRITEp+=sprintf(p, "ATTRIN float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB5);
224 if (components & VB_HAS_COL1)
225 WRITEp+=sprintf(p, "ATTRIN float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB6);
226
227 for (int i = 0; i < 8; ++i)
228 {
229 u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
230 if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
231 WRITEp+=sprintf(p, "ATTRIN float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB8 + i);
232 }
233
234 // Let's set up attributes
235 if (xfregs.numTexGen.numTexGens < 7)
236 {
237 for (int i = 0; i < 8; ++i)
238 WRITEp+=sprintf(p, "VARYOUT float3 uv%d_2;\n", i);
239 WRITEp+=sprintf(p, "VARYOUT float4 clipPos_2;\n");
240 if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
241 WRITEp+=sprintf(p, "VARYOUT float4 Normal_2;\n");
242 }
243 else
244 {
245 // wpos is in w of first 4 texcoords
246 if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
247 {
248 for (int i = 0; i < 8; ++i)
249 WRITEp+=sprintf(p, "VARYOUT float4 uv%d_2;\n", i);
250 }
251 else
252 {
253 for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
254 WRITEp+=sprintf(p, "VARYOUT float%d uv%d_2;\n", i < 4 ? 4 : 3 , i);
255 }
256 }
257 WRITEp+=sprintf(p, "VARYOUT float4 colors_02;\n");
258 WRITEp+=sprintf(p, "VARYOUT float4 colors_12;\n");
259
260 WRITEp+=sprintf(p, "void main()\n{\n");
261 }
262 else
263 {
264 WRITEp+=sprintf(p, "VS_OUTPUT main(\n");
265
266 // inputs
267 if (components & VB_HAS_NRM0)
268 WRITEp+=sprintf(p, " float3 rawnorm0 : NORMAL0,\n");
269 if (components & VB_HAS_NRM1)
270 {
271 if (is_d3d)
272 WRITEp+=sprintf(p, " float3 rawnorm1 : NORMAL1,\n");
273 else
274 WRITEp+=sprintf(p, " float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB3);
275 }
276 if (components & VB_HAS_NRM2)
277 {
278 if (is_d3d)
279 WRITEp+=sprintf(p, " float3 rawnorm2 : NORMAL2,\n");
280 else
281 WRITEp+=sprintf(p, " float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB4);
282 }
283 if (components & VB_HAS_COL0)
284 {
285 WRITEp+=sprintf(p, " float4 color0 : COLOR0,\n");
286 }
287 if (components & VB_HAS_COL1)
288 {
289 WRITEp+=sprintf(p, " float4 color1 : COLOR1,\n");
290 }
291 for (int i = 0; i < 8; ++i)
292 {
293 u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
294 if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
295 WRITEp+=sprintf(p, " float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
296 }
297 if (components & VB_HAS_POSMTXIDX)
298 {
299 if (is_d3d)
300 WRITEp+=sprintf(p, " float4 blend_indices : BLENDINDICES,\n");
301 else
302 WRITEp+=sprintf(p, " float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB1);
303 }
304 WRITEp+=sprintf(p, " float4 rawpos : POSITION) {\n");
305 }
306 WRITEp+=sprintf(p, "VS_OUTPUT o;\n");
307
308 // transforms
309 if (components & VB_HAS_POSMTXIDX)
310 {
311 if (ApiType & API_D3D9)
312 {
313 WRITEp+=sprintf(p, "int4 indices = D3DCOLORtoUBYTE4(blend_indices);\n");
314 WRITEp+=sprintf(p, "int posmtx = indices.x;\n");
315 }
316 else if (ApiType == API_D3D11)
317 {
318 WRITEp+=sprintf(p, "int posmtx = blend_indices.x * 255.0f;\n");
319 }
320 else
321 {
322 WRITEp+=sprintf(p, "int posmtx = int(fposmtx);\n");
323 }
324
325 WRITEp+=sprintf(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES"ctrmtx""[posmtx], rawpos), dot(" I_TRANSFORMMATRICES"ctrmtx""[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES"ctrmtx""[posmtx+2], rawpos), 1);\n");
326
327 if (components & VB_HAS_NRMALL) {
328 WRITEp+=sprintf(p, "int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n");
329 WRITEp+=sprintf(p, "float3 N0 = " I_NORMALMATRICES"cnmtx""[normidx].xyz, N1 = " I_NORMALMATRICES"cnmtx""[normidx+1].xyz, N2 = " I_NORMALMATRICES"cnmtx""[normidx+2].xyz;\n");
330 }
331
332 if (components & VB_HAS_NRM0)
333 WRITEp+=sprintf(p, "float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, rawnorm0)));\n");
334 if (components & VB_HAS_NRM1)
335 WRITEp+=sprintf(p, "float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n");
336 if (components & VB_HAS_NRM2)
337 WRITEp+=sprintf(p, "float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n");
338 }
339 else
340 {
341 WRITEp+=sprintf(p, "float4 pos = float4(dot(" I_POSNORMALMATRIX"cpnmtx""[0], rawpos), dot(" I_POSNORMALMATRIX"cpnmtx""[1], rawpos), dot(" I_POSNORMALMATRIX"cpnmtx""[2], rawpos), 1.0f);\n");
342 if (components & VB_HAS_NRM0)
343 WRITEp+=sprintf(p, "float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX"cpnmtx""[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"cpnmtx""[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"cpnmtx""[5].xyz, rawnorm0)));\n");
344 if (components & VB_HAS_NRM1)
345 WRITEp+=sprintf(p, "float3 _norm1 = float3(dot(" I_POSNORMALMATRIX"cpnmtx""[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"cpnmtx""[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"cpnmtx""[5].xyz, rawnorm1));\n");
346 if (components & VB_HAS_NRM2)
347 WRITEp+=sprintf(p, "float3 _norm2 = float3(dot(" I_POSNORMALMATRIX"cpnmtx""[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"cpnmtx""[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"cpnmtx""[5].xyz, rawnorm2));\n");
348 }
349
350 if (!(components & VB_HAS_NRM0))
351 WRITEp+=sprintf(p, "float3 _norm0 = float3(0.0f, 0.0f, 0.0f);\n");
352
353 WRITEp+=sprintf(p, "o.pos = float4(dot(" I_PROJECTION"cproj""[0], pos), dot(" I_PROJECTION"cproj""[1], pos), dot(" I_PROJECTION"cproj""[2], pos), dot(" I_PROJECTION"cproj""[3], pos));\n");
354
355 WRITEp+=sprintf(p, "float4 mat, lacc;\n"
356 "float3 ldir, h;\n"
357 "float dist, dist2, attn;\n");
358
359 if (xfregs.numChan.numColorChans == 0)
360 {
361 if (components & VB_HAS_COL0)
362 WRITEp+=sprintf(p, "o.colors_0 = color0;\n");
363 else
364 WRITEp+=sprintf(p, "o.colors_0 = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
365 }
366
367 // TODO: This probably isn't necessary if pixel lighting is enabled.
368 p = GenerateLightingShader(p, components, I_MATERIALS"cmtrl", I_LIGHTS"clights", "color", "o.colors_");
369
370 if (xfregs.numChan.numColorChans < 2)
371 {
372 if (components & VB_HAS_COL1)
373 WRITEp+=sprintf(p, "o.colors_1 = color1;\n");
374 else
375 WRITEp+=sprintf(p, "o.colors_1 = o.colors_0;\n");
376 }
377 // special case if only pos and tex coord 0 and tex coord input is AB11
378 // donko - this has caused problems in some games. removed for now.
379 bool texGenSpecialCase = false;
380 /*bool texGenSpecialCase =
381 ((g_VtxDesc.Hex & 0x60600L) == g_VtxDesc.Hex) && // only pos and tex coord 0
382 (g_VtxDesc.Tex0Coord != NOT_PRESENT) &&
383 (xfregs.texcoords[0].texmtxinfo.inputform == XF_TEXINPUT_AB11);
384 */
385
386 // transform texcoords
387 WRITEp+=sprintf(p, "float4 coord = float4(0.0f, 0.0f, 1.0f, 1.0f);\n");
388 for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
389 {
390 TexMtxInfo& texinfo = xfregs.texMtxInfo[i];
391
392 WRITEp+=sprintf(p, "{\n");
393 WRITEp+=sprintf(p, "coord = float4(0.0f, 0.0f, 1.0f, 1.0f);\n");
394
395 switch (texinfo.sourcerow)
396 {
397 case XF_SRCGEOM_INROW0:
398 _assert_( texinfo.inputform == XF_TEXINPUT_ABC1 ){};
399 WRITEp+=sprintf(p, "coord = rawpos;\n"); // pos.w is 1
400 break;
401 case XF_SRCNORMAL_INROW1:
402 if (components & VB_HAS_NRM0)
403 {
404 _assert_( texinfo.inputform == XF_TEXINPUT_ABC1 ){};
405 WRITEp+=sprintf(p, "coord = float4(rawnorm0.xyz, 1.0f);\n");
406 }
407 break;
408 case XF_SRCCOLORS_INROW2:
409 _assert_( texinfo.texgentype == XF_TEXGEN_COLOR_STRGBC0 || texinfo.texgentype == XF_TEXGEN_COLOR_STRGBC1 ){};
410 break;
411 case XF_SRCBINORMAL_T_INROW3:
412 if (components & VB_HAS_NRM1)
413 {
414 _assert_( texinfo.inputform == XF_TEXINPUT_ABC1 ){};
415 WRITEp+=sprintf(p, "coord = float4(rawnorm1.xyz, 1.0f);\n");
416 }
417 break;
418 case XF_SRCBINORMAL_B_INROW4:
419 if (components & VB_HAS_NRM2)
420 {
421 _assert_( texinfo.inputform == XF_TEXINPUT_ABC1 ){};
422 WRITEp+=sprintf(p, "coord = float4(rawnorm2.xyz, 1.0f);\n");
423 }
424 break;
425 default:
426 _assert_(texinfo.sourcerow <= XF_SRCTEX7_INROW){};
427 if (components & (VB_HAS_UV0<<(texinfo.sourcerow - XF_SRCTEX0_INROW5)) )
428 WRITEp+=sprintf(p, "coord = float4(tex%d.x, tex%d.y, 1.0f, 1.0f);\n", texinfo.sourcerow - XF_SRCTEX0_INROW5, texinfo.sourcerow - XF_SRCTEX0_INROW5);
429 break;
430 }
431
432 // first transformation
433 switch (texinfo.texgentype)
434 {
435 case XF_TEXGEN_EMBOSS_MAP1: // calculate tex coords into bump map
436
437 if (components & (VB_HAS_NRM1|VB_HAS_NRM2))
438 {
439 // transform the light dir into tangent space
440 WRITEp+=sprintf(p, "ldir = normalize(" I_LIGHTS"clights""[5*%d + 3].xyz - pos.xyz);\n", texinfo.embosslightshift);
441 WRITEp+=sprintf(p, "o.tex%d.xyz = o.tex%d.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0f);\n", i, texinfo.embosssourceshift);
442 }
443 else
444 {
445 _assert_(0){}; // should have normals
446 WRITEp+=sprintf(p, "o.tex%d.xyz = o.tex%d.xyz;\n", i, texinfo.embosssourceshift);
447 }
448
449 break;
450 case XF_TEXGEN_COLOR_STRGBC02:
451 _assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW){};
452 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(o.colors_0.x, o.colors_0.y, 1);\n", i);
453 break;
454 case XF_TEXGEN_COLOR_STRGBC13:
455 _assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW){};
456 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(o.colors_1.x, o.colors_1.y, 1);\n", i);
457 break;
458 case XF_TEXGEN_REGULAR0:
459 default:
460 if (components & (VB_HAS_TEXMTXIDX0<<i))
461 {
462 WRITEp+=sprintf(p, "int tmp = int(tex%d.z);\n", i);
463 if (texinfo.projection == XF_TEXPROJ_STQ1)
464 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"ctrmtx""[tmp]), dot(coord, " I_TRANSFORMMATRICES"ctrmtx""[tmp+1]), dot(coord, " I_TRANSFORMMATRICES"ctrmtx""[tmp+2]));\n", i);
465 else
466 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"ctrmtx""[tmp]), dot(coord, " I_TRANSFORMMATRICES"ctrmtx""[tmp+1]), 1);\n", i);
467 }
468 else
469 {
470 if (texinfo.projection == XF_TEXPROJ_STQ1)
471 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"ctexmtx""[%d]), dot(coord, " I_TEXMATRICES"ctexmtx""[%d]), dot(coord, " I_TEXMATRICES"ctexmtx""[%d]));\n", i, 3*i, 3*i+1, 3*i+2);
472 else
473 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"ctexmtx""[%d]), dot(coord, " I_TEXMATRICES"ctexmtx""[%d]), 1);\n", i, 3*i, 3*i+1);
474 }
475 break;
476 }
477
478 // CHECKME: does this only work for regular tex gen types?
479 if (xfregs.dualTexTrans.enabled && texinfo.texgentype == XF_TEXGEN_REGULAR0)
480 {
481 const PostMtxInfo& postInfo = xfregs.postMtxInfo[i];
482
483 int postidx = postInfo.index;
484 WRITEp+=sprintf(p, "float4 P0 = " I_POSTTRANSFORMMATRICES"cpostmtx""[%d];\n"
485 "float4 P1 = " I_POSTTRANSFORMMATRICES"cpostmtx""[%d];\n"
486 "float4 P2 = " I_POSTTRANSFORMMATRICES"cpostmtx""[%d];\n",
487 postidx&0x3f, (postidx+1)&0x3f, (postidx+2)&0x3f);
488
489 if (texGenSpecialCase)
490 {
491 // no normalization
492 // q of input is 1
493 // q of output is unknown
494
495 // multiply by postmatrix
496 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(dot(P0.xy, o.tex%d.xy) + P0.z + P0.w, dot(P1.xy, o.tex%d.xy) + P1.z + P1.w, 0.0f);\n", i, i, i);
497 }
498 else
499 {
500 if (postInfo.normalize)
501 WRITEp+=sprintf(p, "o.tex%d.xyz = normalize(o.tex%d.xyz);\n", i, i);
502
503 // multiply by postmatrix
504 WRITEp+=sprintf(p, "o.tex%d.xyz = float3(dot(P0.xyz, o.tex%d.xyz) + P0.w, dot(P1.xyz, o.tex%d.xyz) + P1.w, dot(P2.xyz, o.tex%d.xyz) + P2.w);\n", i, i, i, i);
505 }
506 }
507
508 WRITEp+=sprintf(p, "}\n");
509 }
510
511 // clipPos/w needs to be done in pixel shader, not here
512 if (xfregs.numTexGen.numTexGens < 7)
513 {
514 WRITEp+=sprintf(p, "o.clipPos = float4(pos.x,pos.y,o.pos.z,o.pos.w);\n");
515 }
516 else
517 {
518 WRITEp+=sprintf(p, "o.tex0.w = pos.x;\n");
519 WRITEp+=sprintf(p, "o.tex1.w = pos.y;\n");
520 WRITEp+=sprintf(p, "o.tex2.w = o.pos.z;\n");
521 WRITEp+=sprintf(p, "o.tex3.w = o.pos.w;\n");
522 }
523
524 if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
525 {
526 if (xfregs.numTexGen.numTexGens < 7)
527 {
528 WRITEp+=sprintf(p, "o.Normal = float4(_norm0.x,_norm0.y,_norm0.z,pos.z);\n");
529 }
530 else
531 {
532 WRITEp+=sprintf(p, "o.tex4.w = _norm0.x;\n");
533 WRITEp+=sprintf(p, "o.tex5.w = _norm0.y;\n");
534 WRITEp+=sprintf(p, "o.tex6.w = _norm0.z;\n");
535 if (xfregs.numTexGen.numTexGens < 8)
536 WRITEp+=sprintf(p, "o.tex7 = pos.xyzz;\n");
537 else
538 WRITEp+=sprintf(p, "o.tex7.w = pos.z;\n");
539 }
540
541 if (components & VB_HAS_COL0)
542 WRITEp+=sprintf(p, "o.colors_0 = color0;\n");
543
544 if (components & VB_HAS_COL1)
545 WRITEp+=sprintf(p, "o.colors_1 = color1;\n");
546 }
547
548 //write the true depth value, if the game uses depth textures pixel shaders will override with the correct values
549 //if not early z culling will improve speed
550 if (is_d3d)
551 {
552 WRITEp+=sprintf(p, "o.pos.z = " I_DEPTHPARAMS"cDepth"".x * o.pos.w + o.pos.z * " I_DEPTHPARAMS"cDepth"".y;\n");
553 }
554 else
555 {
556 // this results in a scale from -1..0 to -1..1 after perspective
557 // divide
558 WRITEp+=sprintf(p, "o.pos.z = o.pos.w + o.pos.z * 2.0f;\n");
559
560 // Sonic Unleashed puts its final rendering at the near or
561 // far plane of the viewing frustrum(actually box, they use
562 // orthogonal projection for that), and we end up putting it
563 // just beyond, and the rendering gets clipped away. (The
564 // primitive gets dropped)
565 WRITEp+=sprintf(p, "o.pos.z = o.pos.z * 1048575.0f/1048576.0f;\n");
566
567 // the next steps of the OGL pipeline are:
568 // (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology
569 // clipping to -w_c <= (x_c,y_c,z_c) <= w_c
570 // (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide
571 // z_w = (f-n)/2*z_d + (n+f)/2
572 // z_w now contains the value to go to the 0..1 depth buffer
573
574 //trying to get the correct semantic while not using glDepthRange
575 //seems to get rather complicated
576 }
577
578 if (ApiType & API_D3D9)
579 {
580 // D3D9 is addressing pixel centers instead of pixel boundaries in clip space.
581 // Thus we need to offset the final position by half a pixel
582 WRITEp+=sprintf(p, "o.pos = o.pos + float4(" I_DEPTHPARAMS"cDepth"".z, " I_DEPTHPARAMS"cDepth"".w, 0.f, 0.f);\n");
583 }
584
585 if(ApiType == API_OPENGL)
586 {
587 // Bit ugly here
588 // TODO: Make pretty
589 // Will look better when we bind uniforms in GLSL 1.3
590 // clipPos/w needs to be done in pixel shader, not here
591
592 if (xfregs.numTexGen.numTexGens < 7)
593 {
594 for (unsigned int i = 0; i < 8; ++i)
595 {
596 if(i < xfregs.numTexGen.numTexGens)
597 WRITEp+=sprintf(p, " uv%d_2.xyz = o.tex%d;\n", i, i);
598 else
599 WRITEp+=sprintf(p, " uv%d_2.xyz = float3(0.0f, 0.0f, 0.0f);\n", i);
600 }
601
602 WRITEp+=sprintf(p, " clipPos_2 = o.clipPos;\n");
603
604 if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
605 WRITEp+=sprintf(p, " Normal_2 = o.Normal;\n");
606 }
607 else
608 {
609 // clip position is in w of first 4 texcoords
610 if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
611 {
612 for (int i = 0; i < 8; ++i)
613 WRITEp+=sprintf(p, " uv%d_2 = o.tex%d;\n", i, i);
614 }
615 else
616 {
617 for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
618 WRITEp+=sprintf(p, " uv%d_2%s = o.tex%d;\n", i, i < 4 ? ".xyzw" : ".xyz" , i);
619 }
620 }
621 WRITEp+=sprintf(p, "colors_02 = o.colors_0;\n");
622 WRITEp+=sprintf(p, "colors_12 = o.colors_1;\n");
623 WRITEp+=sprintf(p, "gl_Position = o.pos;\n");
624 WRITEp+=sprintf(p, "}\n");
625 }
626 else
627 {
628 WRITEp+=sprintf(p, "return o;\n}\n");
629 }
630
631 if (text[sizeof(text) - 1] != 0x7C)
632 PanicAlert("VertexShader generator - buffer too small, canary has been eaten!")MsgAlert(false, WARNING, "VertexShader generator - buffer too small, canary has been eaten!"
)
;
633 setlocale(LC_NUMERIC1, ""); // restore locale
634 return text;
635}