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