• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
7 //
8 
9 #include "precompiled.h"
10 
11 #include "libGLESv2/DynamicHLSL.h"
12 #include "libGLESv2/Shader.h"
13 #include "libGLESv2/Program.h"
14 #include "libGLESv2/renderer/Renderer.h"
15 #include "common/utilities.h"
16 #include "libGLESv2/ProgramBinary.h"
17 #include "libGLESv2/formatutils.h"
18 #include "common/blocklayout.h"
19 
Str(int i)20 static std::string Str(int i)
21 {
22     char buffer[20];
23     snprintf(buffer, sizeof(buffer), "%d", i);
24     return buffer;
25 }
26 
27 namespace gl_d3d
28 {
29 
HLSLComponentTypeString(GLenum componentType)30 std::string HLSLComponentTypeString(GLenum componentType)
31 {
32     switch (componentType)
33     {
34       case GL_UNSIGNED_INT:         return "uint";
35       case GL_INT:                  return "int";
36       case GL_UNSIGNED_NORMALIZED:
37       case GL_SIGNED_NORMALIZED:
38       case GL_FLOAT:                return "float";
39       default: UNREACHABLE();       return "not-component-type";
40     }
41 }
42 
HLSLComponentTypeString(GLenum componentType,int componentCount)43 std::string HLSLComponentTypeString(GLenum componentType, int componentCount)
44 {
45     return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : "");
46 }
47 
HLSLMatrixTypeString(GLenum type)48 std::string HLSLMatrixTypeString(GLenum type)
49 {
50     switch (type)
51     {
52       case GL_FLOAT_MAT2:     return "float2x2";
53       case GL_FLOAT_MAT3:     return "float3x3";
54       case GL_FLOAT_MAT4:     return "float4x4";
55       case GL_FLOAT_MAT2x3:   return "float2x3";
56       case GL_FLOAT_MAT3x2:   return "float3x2";
57       case GL_FLOAT_MAT2x4:   return "float2x4";
58       case GL_FLOAT_MAT4x2:   return "float4x2";
59       case GL_FLOAT_MAT3x4:   return "float3x4";
60       case GL_FLOAT_MAT4x3:   return "float4x3";
61       default: UNREACHABLE(); return "not-matrix-type";
62     }
63 }
64 
HLSLTypeString(GLenum type)65 std::string HLSLTypeString(GLenum type)
66 {
67     if (gl::IsMatrixType(type))
68     {
69         return HLSLMatrixTypeString(type);
70     }
71 
72     return HLSLComponentTypeString(gl::UniformComponentType(type), gl::UniformComponentCount(type));
73 }
74 
75 }
76 
77 namespace gl
78 {
79 
ArrayString(unsigned int i)80 std::string ArrayString(unsigned int i)
81 {
82     return (i == GL_INVALID_INDEX ? "" : "[" + Str(i) + "]");
83 }
84 
85 const std::string DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
86 
DynamicHLSL(rx::Renderer * const renderer)87 DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
88     : mRenderer(renderer)
89 {
90 }
91 
packVarying(PackedVarying * varying,const int maxVaryingVectors,VaryingPacking packing)92 static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, VaryingPacking packing)
93 {
94     GLenum transposedType = TransposeMatrixType(varying->type);
95 
96     // matrices within varying structs are not transposed
97     int registers = (varying->isStruct() ? HLSLVariableRegisterCount(*varying) : VariableRowCount(transposedType)) * varying->elementCount();
98     int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
99 
100     if (elements >= 2 && elements <= 4)
101     {
102         for (int r = 0; r <= maxVaryingVectors - registers; r++)
103         {
104             bool available = true;
105 
106             for (int y = 0; y < registers && available; y++)
107             {
108                 for (int x = 0; x < elements && available; x++)
109                 {
110                     if (packing[r + y][x])
111                     {
112                         available = false;
113                     }
114                 }
115             }
116 
117             if (available)
118             {
119                 varying->registerIndex = r;
120 
121                 for (int y = 0; y < registers; y++)
122                 {
123                     for (int x = 0; x < elements; x++)
124                     {
125                         packing[r + y][x] = &*varying;
126                     }
127                 }
128 
129                 return true;
130             }
131         }
132 
133         if (elements == 2)
134         {
135             for (int r = maxVaryingVectors - registers; r >= 0; r--)
136             {
137                 bool available = true;
138 
139                 for (int y = 0; y < registers && available; y++)
140                 {
141                     for (int x = 2; x < 4 && available; x++)
142                     {
143                         if (packing[r + y][x])
144                         {
145                             available = false;
146                         }
147                     }
148                 }
149 
150                 if (available)
151                 {
152                     varying->registerIndex = r;
153 
154                     for (int y = 0; y < registers; y++)
155                     {
156                         for (int x = 2; x < 4; x++)
157                         {
158                             packing[r + y][x] = &*varying;
159                         }
160                     }
161 
162                     return true;
163                 }
164             }
165         }
166     }
167     else if (elements == 1)
168     {
169         int space[4] = { 0 };
170 
171         for (int y = 0; y < maxVaryingVectors; y++)
172         {
173             for (int x = 0; x < 4; x++)
174             {
175                 space[x] += packing[y][x] ? 0 : 1;
176             }
177         }
178 
179         int column = 0;
180 
181         for (int x = 0; x < 4; x++)
182         {
183             if (space[x] >= registers && space[x] < space[column])
184             {
185                 column = x;
186             }
187         }
188 
189         if (space[column] >= registers)
190         {
191             for (int r = 0; r < maxVaryingVectors; r++)
192             {
193                 if (!packing[r][column])
194                 {
195                     varying->registerIndex = r;
196 
197                     for (int y = r; y < r + registers; y++)
198                     {
199                         packing[y][column] = &*varying;
200                     }
201 
202                     break;
203                 }
204             }
205 
206             return true;
207         }
208     }
209     else UNREACHABLE();
210 
211     return false;
212 }
213 
214 // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
215 // Returns the number of used varying registers, or -1 if unsuccesful
packVaryings(InfoLog & infoLog,VaryingPacking packing,FragmentShader * fragmentShader,VertexShader * vertexShader,const std::vector<std::string> & transformFeedbackVaryings)216 int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, FragmentShader *fragmentShader,
217                               VertexShader *vertexShader, const std::vector<std::string>& transformFeedbackVaryings)
218 {
219     const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
220 
221     vertexShader->resetVaryingsRegisterAssignment();
222     fragmentShader->resetVaryingsRegisterAssignment();
223 
224     std::set<std::string> packedVaryings;
225 
226     for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
227     {
228         PackedVarying *varying = &fragmentShader->mVaryings[varyingIndex];
229         if (packVarying(varying, maxVaryingVectors, packing))
230         {
231             packedVaryings.insert(varying->name);
232         }
233         else
234         {
235             infoLog.append("Could not pack varying %s", varying->name.c_str());
236             return -1;
237         }
238     }
239 
240     for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
241     {
242         const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
243         if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
244         {
245             bool found = false;
246             for (unsigned int varyingIndex = 0; varyingIndex < vertexShader->mVaryings.size(); varyingIndex++)
247             {
248                 PackedVarying *varying = &vertexShader->mVaryings[varyingIndex];
249                 if (transformFeedbackVarying == varying->name)
250                 {
251                     if (!packVarying(varying, maxVaryingVectors, packing))
252                     {
253                         infoLog.append("Could not pack varying %s", varying->name.c_str());
254                         return -1;
255                     }
256 
257                     found = true;
258                     break;
259                 }
260             }
261 
262             if (!found && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize")
263             {
264                 infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str());
265                 return -1;
266             }
267         }
268     }
269 
270     // Return the number of used registers
271     int registers = 0;
272 
273     for (int r = 0; r < maxVaryingVectors; r++)
274     {
275         if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
276         {
277             registers++;
278         }
279     }
280 
281     return registers;
282 }
283 
generateVaryingHLSL(VertexShader * shader,const std::string & varyingSemantic,std::vector<LinkedVarying> * linkedVaryings) const284 std::string DynamicHLSL::generateVaryingHLSL(VertexShader *shader, const std::string &varyingSemantic,
285                                              std::vector<LinkedVarying> *linkedVaryings) const
286 {
287     std::string varyingHLSL;
288 
289     for (unsigned int varyingIndex = 0; varyingIndex < shader->mVaryings.size(); varyingIndex++)
290     {
291         const PackedVarying &varying = shader->mVaryings[varyingIndex];
292         if (varying.registerAssigned())
293         {
294             GLenum transposedType = TransposeMatrixType(varying.type);
295             int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
296 
297             for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
298             {
299                 for (int row = 0; row < variableRows; row++)
300                 {
301                     switch (varying.interpolation)
302                     {
303                       case INTERPOLATION_SMOOTH:   varyingHLSL += "    ";                 break;
304                       case INTERPOLATION_FLAT:     varyingHLSL += "    nointerpolation "; break;
305                       case INTERPOLATION_CENTROID: varyingHLSL += "    centroid ";        break;
306                       default:  UNREACHABLE();
307                     }
308 
309                     unsigned int semanticIndex = elementIndex * variableRows + varying.registerIndex + row;
310                     std::string n = Str(semanticIndex);
311 
312                     std::string typeString;
313 
314                     if (varying.isStruct())
315                     {
316                         // matrices within structs are not transposed, so
317                         // do not use the special struct prefix "rm"
318                         typeString = decorateVariable(varying.structName);
319                     }
320                     else
321                     {
322                         GLenum componentType = UniformComponentType(transposedType);
323                         int columnCount = VariableColumnCount(transposedType);
324                         typeString = gl_d3d::HLSLComponentTypeString(componentType, columnCount);
325                     }
326                     varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
327                 }
328             }
329 
330             if (linkedVaryings)
331             {
332                 linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(),
333                                                         varyingSemantic, varying.registerIndex,
334                                                         variableRows * varying.elementCount()));
335             }
336         }
337     }
338 
339     return varyingHLSL;
340 }
341 
generateInputLayoutHLSL(const VertexFormat inputLayout[],const Attribute shaderAttributes[]) const342 std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[], const Attribute shaderAttributes[]) const
343 {
344     std::string structHLSL, initHLSL;
345 
346     int semanticIndex = 0;
347     unsigned int inputIndex = 0;
348 
349     for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
350     {
351         ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
352 
353         const VertexFormat &vertexFormat = inputLayout[inputIndex];
354         const Attribute &shaderAttribute = shaderAttributes[attributeIndex];
355 
356         if (!shaderAttribute.name.empty())
357         {
358             // HLSL code for input structure
359             if (IsMatrixType(shaderAttribute.type))
360             {
361                 // Matrix types are always transposed
362                 structHLSL += "    " + gl_d3d::HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
363             }
364             else
365             {
366                 GLenum componentType = mRenderer->getVertexComponentType(vertexFormat);
367                 structHLSL += "    " + gl_d3d::HLSLComponentTypeString(componentType, UniformComponentCount(shaderAttribute.type));
368             }
369 
370             structHLSL += " " + decorateVariable(shaderAttribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n";
371             semanticIndex += AttributeRegisterCount(shaderAttribute.type);
372 
373             // HLSL code for initialization
374             initHLSL += "    " + decorateVariable(shaderAttribute.name) + " = ";
375 
376             // Mismatched vertex attribute to vertex input may result in an undefined
377             // data reinterpretation (eg for pure integer->float, float->pure integer)
378             // TODO: issue warning with gl debug info extension, when supported
379             if (IsMatrixType(shaderAttribute.type) ||
380                 (mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0)
381             {
382                 initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute);
383             }
384             else
385             {
386                 initHLSL += "input." + decorateVariable(shaderAttribute.name);
387             }
388 
389             initHLSL += ";\n";
390 
391             inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
392         }
393     }
394 
395     return "struct VS_INPUT\n"
396            "{\n" +
397            structHLSL +
398            "};\n"
399            "\n"
400            "void initAttributes(VS_INPUT input)\n"
401            "{\n" +
402            initHLSL +
403            "}\n";
404 }
405 
generateShaderLinkHLSL(InfoLog & infoLog,int registers,const VaryingPacking packing,std::string & pixelHLSL,std::string & vertexHLSL,FragmentShader * fragmentShader,VertexShader * vertexShader,const std::vector<std::string> & transformFeedbackVaryings,std::vector<LinkedVarying> * linkedVaryings,std::map<int,VariableLocation> * programOutputVars) const406 bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing,
407                                          std::string& pixelHLSL, std::string& vertexHLSL,
408                                          FragmentShader *fragmentShader, VertexShader *vertexShader,
409                                          const std::vector<std::string>& transformFeedbackVaryings,
410                                          std::vector<LinkedVarying> *linkedVaryings,
411                                          std::map<int, VariableLocation> *programOutputVars) const
412 {
413     if (pixelHLSL.empty() || vertexHLSL.empty())
414     {
415         return false;
416     }
417 
418     bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
419     bool usesFragColor = fragmentShader->mUsesFragColor;
420     bool usesFragData = fragmentShader->mUsesFragData;
421     if (usesFragColor && usesFragData)
422     {
423         infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
424         return false;
425     }
426 
427     // Write the HLSL input/output declarations
428     const int shaderModel = mRenderer->getMajorShaderModel();
429     const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
430 
431     const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
432 
433     // Two cases when writing to gl_FragColor and using ESSL 1.0:
434     // - with a 3.0 context, the output color is copied to channel 0
435     // - with a 2.0 context, the output color is broadcast to all channels
436     const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
437     const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
438 
439     int shaderVersion = vertexShader->getShaderVersion();
440 
441     if (registersNeeded > maxVaryingVectors)
442     {
443         infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
444 
445         return false;
446     }
447 
448     std::string varyingSemantic = (vertexShader->mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
449     std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
450     std::string dxPositionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
451     std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
452 
453     std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, linkedVaryings);
454 
455     // special varyings that use reserved registers
456     int reservedRegisterIndex = registers;
457 
458     unsigned int glPositionSemanticIndex = reservedRegisterIndex++;
459     std::string glPositionSemantic = varyingSemantic;
460 
461     std::string fragCoordSemantic;
462     unsigned int fragCoordSemanticIndex = 0;
463     if (fragmentShader->mUsesFragCoord)
464     {
465         fragCoordSemanticIndex = reservedRegisterIndex++;
466         fragCoordSemantic = varyingSemantic;
467     }
468 
469     std::string pointCoordSemantic;
470     unsigned int pointCoordSemanticIndex = 0;
471     if (fragmentShader->mUsesPointCoord)
472     {
473         // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
474         // In DX11 we compute this in the GS.
475         if (shaderModel == 3)
476         {
477             pointCoordSemanticIndex = 0;
478             pointCoordSemantic = "TEXCOORD0";
479         }
480         else if (shaderModel >= 4)
481         {
482             pointCoordSemanticIndex = reservedRegisterIndex++;
483             pointCoordSemantic = varyingSemantic;
484         }
485     }
486 
487     // Add stub string to be replaced when shader is dynamically defined by its layout
488     vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n";
489 
490     vertexHLSL += "struct VS_OUTPUT\n"
491                   "{\n";
492 
493     if (shaderModel < 4)
494     {
495         vertexHLSL += "    float4 _dx_Position : " + dxPositionSemantic + ";\n";
496         vertexHLSL += "    float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n";
497         linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1));
498 
499     }
500 
501     vertexHLSL += varyingHLSL;
502 
503     if (fragmentShader->mUsesFragCoord)
504     {
505         vertexHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + Str(fragCoordSemanticIndex) + ";\n";
506         linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, fragCoordSemantic, fragCoordSemanticIndex, 1));
507     }
508 
509     if (vertexShader->mUsesPointSize && shaderModel >= 3)
510     {
511         vertexHLSL += "    float gl_PointSize : PSIZE;\n";
512         linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1));
513     }
514 
515     if (shaderModel >= 4)
516     {
517         vertexHLSL += "    float4 _dx_Position : " + dxPositionSemantic + ";\n";
518         vertexHLSL += "    float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n";
519         linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1));
520     }
521 
522     vertexHLSL += "};\n"
523                   "\n"
524                   "VS_OUTPUT main(VS_INPUT input)\n"
525                   "{\n"
526                   "    initAttributes(input);\n";
527 
528     if (shaderModel >= 4)
529     {
530         vertexHLSL += "\n"
531                       "    gl_main();\n"
532                       "\n"
533                       "    VS_OUTPUT output;\n"
534                       "    output.gl_Position = gl_Position;\n"
535                       "    output._dx_Position.x = gl_Position.x;\n"
536                       "    output._dx_Position.y = -gl_Position.y;\n"
537                       "    output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
538                       "    output._dx_Position.w = gl_Position.w;\n";
539     }
540     else
541     {
542         vertexHLSL += "\n"
543                       "    gl_main();\n"
544                       "\n"
545                       "    VS_OUTPUT output;\n"
546                       "    output.gl_Position = gl_Position;\n"
547                       "    output._dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
548                       "    output._dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
549                       "    output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
550                       "    output._dx_Position.w = gl_Position.w;\n";
551     }
552 
553     if (vertexShader->mUsesPointSize && shaderModel >= 3)
554     {
555         vertexHLSL += "    output.gl_PointSize = gl_PointSize;\n";
556     }
557 
558     if (fragmentShader->mUsesFragCoord)
559     {
560         vertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
561     }
562 
563     for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++)
564     {
565         const PackedVarying &varying = vertexShader->mVaryings[vertVaryingIndex];
566         if (varying.registerAssigned())
567         {
568             for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
569             {
570                 int variableRows = (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type)));
571 
572                 for (int row = 0; row < variableRows; row++)
573                 {
574                     int r = varying.registerIndex + elementIndex * variableRows + row;
575                     vertexHLSL += "    output.v" + Str(r);
576 
577                     bool sharedRegister = false;   // Register used by multiple varyings
578 
579                     for (int x = 0; x < 4; x++)
580                     {
581                         if (packing[r][x] && packing[r][x] != packing[r][0])
582                         {
583                             sharedRegister = true;
584                             break;
585                         }
586                     }
587 
588                     if(sharedRegister)
589                     {
590                         vertexHLSL += ".";
591 
592                         for (int x = 0; x < 4; x++)
593                         {
594                             if (packing[r][x] == &varying)
595                             {
596                                 switch(x)
597                                 {
598                                   case 0: vertexHLSL += "x"; break;
599                                   case 1: vertexHLSL += "y"; break;
600                                   case 2: vertexHLSL += "z"; break;
601                                   case 3: vertexHLSL += "w"; break;
602                                 }
603                             }
604                         }
605                     }
606 
607                     vertexHLSL += " = _" + varying.name;
608 
609                     if (varying.isArray())
610                     {
611                         vertexHLSL += ArrayString(elementIndex);
612                     }
613 
614                     if (variableRows > 1)
615                     {
616                         vertexHLSL += ArrayString(row);
617                     }
618 
619                     vertexHLSL += ";\n";
620                 }
621             }
622         }
623     }
624 
625     vertexHLSL += "\n"
626                   "    return output;\n"
627                   "}\n";
628 
629     pixelHLSL += "struct PS_INPUT\n"
630                  "{\n";
631 
632     pixelHLSL += varyingHLSL;
633 
634     if (fragmentShader->mUsesFragCoord)
635     {
636         pixelHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + Str(fragCoordSemanticIndex) + ";\n";
637     }
638 
639     if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
640     {
641         pixelHLSL += "    float2 gl_PointCoord : " + pointCoordSemantic + Str(pointCoordSemanticIndex) + ";\n";
642     }
643 
644     // Must consume the PSIZE element if the geometry shader is not active
645     // We won't know if we use a GS until we draw
646     if (vertexShader->mUsesPointSize && shaderModel >= 4)
647     {
648         pixelHLSL += "    float gl_PointSize : PSIZE;\n";
649     }
650 
651     if (fragmentShader->mUsesFragCoord)
652     {
653         if (shaderModel >= 4)
654         {
655             pixelHLSL += "    float4 dx_VPos : SV_Position;\n";
656         }
657         else if (shaderModel >= 3)
658         {
659             pixelHLSL += "    float2 dx_VPos : VPOS;\n";
660         }
661     }
662 
663     pixelHLSL += "};\n"
664                  "\n"
665                  "struct PS_OUTPUT\n"
666                  "{\n";
667 
668     if (shaderVersion < 300)
669     {
670         for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
671         {
672             pixelHLSL += "    float4 gl_Color" + Str(renderTargetIndex) + " : " + targetSemantic + Str(renderTargetIndex) + ";\n";
673         }
674 
675         if (fragmentShader->mUsesFragDepth)
676         {
677             pixelHLSL += "    float gl_Depth : " + depthSemantic + ";\n";
678         }
679     }
680     else
681     {
682         defineOutputVariables(fragmentShader, programOutputVars);
683 
684         const std::vector<Attribute> &shaderOutputVars = fragmentShader->getOutputVariables();
685         for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
686         {
687             const VariableLocation &outputLocation = locationIt->second;
688             const ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
689             const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
690 
691             pixelHLSL += "    " + gl_d3d::HLSLTypeString(outputVariable.type) +
692                          " out_" + outputLocation.name + elementString +
693                          " : " + targetSemantic + Str(locationIt->first) + ";\n";
694         }
695     }
696 
697     pixelHLSL += "};\n"
698                  "\n";
699 
700     if (fragmentShader->mUsesFrontFacing)
701     {
702         if (shaderModel >= 4)
703         {
704             pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
705                          "{\n";
706         }
707         else
708         {
709             pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
710                          "{\n";
711         }
712     }
713     else
714     {
715         pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
716                      "{\n";
717     }
718 
719     if (fragmentShader->mUsesFragCoord)
720     {
721         pixelHLSL += "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
722 
723         if (shaderModel >= 4)
724         {
725             pixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x;\n"
726                          "    gl_FragCoord.y = input.dx_VPos.y;\n";
727         }
728         else if (shaderModel >= 3)
729         {
730             pixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
731                          "    gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
732         }
733         else
734         {
735             // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
736             pixelHLSL += "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
737                          "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
738         }
739 
740         pixelHLSL += "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
741                      "    gl_FragCoord.w = rhw;\n";
742     }
743 
744     if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
745     {
746         pixelHLSL += "    gl_PointCoord.x = input.gl_PointCoord.x;\n";
747         pixelHLSL += "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
748     }
749 
750     if (fragmentShader->mUsesFrontFacing)
751     {
752         if (shaderModel <= 3)
753         {
754             pixelHLSL += "    gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
755         }
756         else
757         {
758             pixelHLSL += "    gl_FrontFacing = isFrontFace;\n";
759         }
760     }
761 
762     for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
763     {
764         const PackedVarying &varying = fragmentShader->mVaryings[varyingIndex];
765         if (varying.registerAssigned())
766         {
767             for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
768             {
769                 GLenum transposedType = TransposeMatrixType(varying.type);
770                 int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
771                 for (int row = 0; row < variableRows; row++)
772                 {
773                     std::string n = Str(varying.registerIndex + elementIndex * variableRows + row);
774                     pixelHLSL += "    _" + varying.name;
775 
776                     if (varying.isArray())
777                     {
778                         pixelHLSL += ArrayString(elementIndex);
779                     }
780 
781                     if (variableRows > 1)
782                     {
783                         pixelHLSL += ArrayString(row);
784                     }
785 
786                     if (varying.isStruct())
787                     {
788                         pixelHLSL += " = input.v" + n + ";\n";   break;
789                     }
790                     else
791                     {
792                         switch (VariableColumnCount(transposedType))
793                         {
794                           case 1: pixelHLSL += " = input.v" + n + ".x;\n";   break;
795                           case 2: pixelHLSL += " = input.v" + n + ".xy;\n";  break;
796                           case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
797                           case 4: pixelHLSL += " = input.v" + n + ";\n";     break;
798                           default: UNREACHABLE();
799                         }
800                     }
801                 }
802             }
803         }
804         else UNREACHABLE();
805     }
806 
807     pixelHLSL += "\n"
808                  "    gl_main();\n"
809                  "\n"
810                  "    PS_OUTPUT output;\n";
811 
812     if (shaderVersion < 300)
813     {
814         for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
815         {
816             unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
817 
818             pixelHLSL += "    output.gl_Color" + Str(renderTargetIndex) + " = gl_Color[" + Str(sourceColorIndex) + "];\n";
819         }
820 
821         if (fragmentShader->mUsesFragDepth)
822         {
823             pixelHLSL += "    output.gl_Depth = gl_Depth;\n";
824         }
825     }
826     else
827     {
828         for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
829         {
830             const VariableLocation &outputLocation = locationIt->second;
831             const std::string &variableName = "out_" + outputLocation.name;
832             const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
833             const std::string &staticVariableName = variableName + ArrayString(outputLocation.element);
834 
835             pixelHLSL += "    output." + outVariableName + " = " + staticVariableName + ";\n";
836         }
837     }
838 
839     pixelHLSL += "\n"
840                  "    return output;\n"
841                  "}\n";
842 
843     return true;
844 }
845 
defineOutputVariables(FragmentShader * fragmentShader,std::map<int,VariableLocation> * programOutputVars) const846 void DynamicHLSL::defineOutputVariables(FragmentShader *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
847 {
848     const std::vector<Attribute> &shaderOutputVars = fragmentShader->getOutputVariables();
849 
850     for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++)
851     {
852         const Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
853         const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
854 
855         if (outputVariable.arraySize > 0)
856         {
857             for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
858             {
859                 const int location = baseLocation + elementIndex;
860                 ASSERT(programOutputVars->count(location) == 0);
861                 (*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
862             }
863         }
864         else
865         {
866             ASSERT(programOutputVars->count(baseLocation) == 0);
867             (*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
868         }
869     }
870 }
871 
generateGeometryShaderHLSL(int registers,FragmentShader * fragmentShader,VertexShader * vertexShader) const872 std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const
873 {
874     // for now we only handle point sprite emulation
875     ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
876     return generatePointSpriteHLSL(registers, fragmentShader, vertexShader);
877 }
878 
generatePointSpriteHLSL(int registers,FragmentShader * fragmentShader,VertexShader * vertexShader) const879 std::string DynamicHLSL::generatePointSpriteHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const
880 {
881     ASSERT(registers >= 0);
882     ASSERT(vertexShader->mUsesPointSize);
883     ASSERT(mRenderer->getMajorShaderModel() >= 4);
884 
885     std::string geomHLSL;
886 
887     std::string varyingSemantic = "TEXCOORD";
888 
889     std::string fragCoordSemantic;
890     std::string pointCoordSemantic;
891 
892     int reservedRegisterIndex = registers;
893 
894     if (fragmentShader->mUsesFragCoord)
895     {
896         fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
897     }
898 
899     if (fragmentShader->mUsesPointCoord)
900     {
901         pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
902     }
903 
904     geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
905                 "\n"
906                 "struct GS_INPUT\n"
907                 "{\n";
908 
909     std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, NULL);
910 
911     geomHLSL += varyingHLSL;
912 
913     if (fragmentShader->mUsesFragCoord)
914     {
915         geomHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
916     }
917 
918     geomHLSL += "    float gl_PointSize : PSIZE;\n"
919                 "    float4 gl_Position : SV_Position;\n"
920                 "};\n"
921                 "\n"
922                 "struct GS_OUTPUT\n"
923                 "{\n";
924 
925     geomHLSL += varyingHLSL;
926 
927     if (fragmentShader->mUsesFragCoord)
928     {
929         geomHLSL += "    float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
930     }
931 
932     if (fragmentShader->mUsesPointCoord)
933     {
934         geomHLSL += "    float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
935     }
936 
937     geomHLSL +=   "    float gl_PointSize : PSIZE;\n"
938                   "    float4 gl_Position : SV_Position;\n"
939                   "};\n"
940                   "\n"
941                   "static float2 pointSpriteCorners[] = \n"
942                   "{\n"
943                   "    float2( 0.5f, -0.5f),\n"
944                   "    float2( 0.5f,  0.5f),\n"
945                   "    float2(-0.5f, -0.5f),\n"
946                   "    float2(-0.5f,  0.5f)\n"
947                   "};\n"
948                   "\n"
949                   "static float2 pointSpriteTexcoords[] = \n"
950                   "{\n"
951                   "    float2(1.0f, 1.0f),\n"
952                   "    float2(1.0f, 0.0f),\n"
953                   "    float2(0.0f, 1.0f),\n"
954                   "    float2(0.0f, 0.0f)\n"
955                   "};\n"
956                   "\n"
957                   "static float minPointSize = " + Str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
958                   "static float maxPointSize = " + Str(mRenderer->getMaxPointSize()) + ".0f;\n"
959                   "\n"
960                   "[maxvertexcount(4)]\n"
961                   "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
962                   "{\n"
963                   "    GS_OUTPUT output = (GS_OUTPUT)0;\n"
964                   "    output.gl_PointSize = input[0].gl_PointSize;\n";
965 
966     for (int r = 0; r < registers; r++)
967     {
968         geomHLSL += "    output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n";
969     }
970 
971     if (fragmentShader->mUsesFragCoord)
972     {
973         geomHLSL += "    output.gl_FragCoord = input[0].gl_FragCoord;\n";
974     }
975 
976     geomHLSL += "    \n"
977                 "    float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
978                 "    float4 gl_Position = input[0].gl_Position;\n"
979                 "    float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
980 
981     for (int corner = 0; corner < 4; corner++)
982     {
983         geomHLSL += "    \n"
984                     "    output.gl_Position = gl_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
985 
986         if (fragmentShader->mUsesPointCoord)
987         {
988             geomHLSL += "    output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n";
989         }
990 
991         geomHLSL += "    outStream.Append(output);\n";
992     }
993 
994     geomHLSL += "    \n"
995                 "    outStream.RestartStrip();\n"
996                 "}\n";
997 
998     return geomHLSL;
999 }
1000 
1001 // This method needs to match OutputHLSL::decorate
decorateVariable(const std::string & name)1002 std::string DynamicHLSL::decorateVariable(const std::string &name)
1003 {
1004     if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
1005     {
1006         return "_" + name;
1007     }
1008 
1009     return name;
1010 }
1011 
generateAttributeConversionHLSL(const VertexFormat & vertexFormat,const ShaderVariable & shaderAttrib) const1012 std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const ShaderVariable &shaderAttrib) const
1013 {
1014     std::string attribString = "input." + decorateVariable(shaderAttrib.name);
1015 
1016     // Matrix
1017     if (IsMatrixType(shaderAttrib.type))
1018     {
1019         return "transpose(" + attribString + ")";
1020     }
1021 
1022     GLenum shaderComponentType = UniformComponentType(shaderAttrib.type);
1023     int shaderComponentCount = UniformComponentCount(shaderAttrib.type);
1024 
1025     // Perform integer to float conversion (if necessary)
1026     bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT);
1027 
1028     if (requiresTypeConversion)
1029     {
1030         // TODO: normalization for 32-bit integer formats
1031         ASSERT(!vertexFormat.mNormalized && !vertexFormat.mPureInteger);
1032         return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
1033     }
1034 
1035     // No conversion necessary
1036     return attribString;
1037 }
1038 
getInputLayoutSignature(const VertexFormat inputLayout[],GLenum signature[]) const1039 void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const
1040 {
1041     for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
1042     {
1043         const VertexFormat &vertexFormat = inputLayout[inputIndex];
1044 
1045         if (vertexFormat.mType == GL_NONE)
1046         {
1047             signature[inputIndex] = GL_NONE;
1048         }
1049         else
1050         {
1051             bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0);
1052             signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE);
1053         }
1054     }
1055 }
1056 
1057 }
1058