blob: d5515768f5515375609012bc83e511aa1cc25490 [file] [log] [blame]
Jamie Madill5f562732014-02-14 16:41:24 -05001//
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
18#include "compiler/translator/HLSLLayoutEncoder.h"
19
20namespace gl_d3d
21{
22
23std::string TypeString(GLenum type)
24{
25 switch (type)
26 {
27 case GL_FLOAT: return "float";
28 case GL_FLOAT_VEC2: return "float2";
29 case GL_FLOAT_VEC3: return "float3";
30 case GL_FLOAT_VEC4: return "float4";
31 case GL_INT: return "int";
32 case GL_INT_VEC2: return "int2";
33 case GL_INT_VEC3: return "int3";
34 case GL_INT_VEC4: return "int4";
35 case GL_UNSIGNED_INT: return "uint";
36 case GL_UNSIGNED_INT_VEC2: return "uint2";
37 case GL_UNSIGNED_INT_VEC3: return "uint3";
38 case GL_UNSIGNED_INT_VEC4: return "uint4";
39 case GL_FLOAT_MAT2: return "float2x2";
40 case GL_FLOAT_MAT3: return "float3x3";
41 case GL_FLOAT_MAT4: return "float4x4";
42 case GL_FLOAT_MAT2x3: return "float2x3";
43 case GL_FLOAT_MAT3x2: return "float3x2";
44 case GL_FLOAT_MAT2x4: return "float2x4";
45 case GL_FLOAT_MAT4x2: return "float4x2";
46 case GL_FLOAT_MAT3x4: return "float3x4";
47 case GL_FLOAT_MAT4x3: return "float4x3";
48 default: UNREACHABLE(); return "invalid-gl-type";
49 }
50}
51
52}
53
54namespace gl
55{
56
57static std::string Str(int i)
58{
59 char buffer[20];
60 snprintf(buffer, sizeof(buffer), "%d", i);
61 return buffer;
62}
63
64static std::string ArrayString(int i)
65{
66 return "[" + Str(i) + "]";
67}
68
69std::string ArrayString(unsigned int i)
70{
71 return (i == GL_INVALID_INDEX ? "" : "[" + Str(i) + "]");
72}
73
Jamie Madillc5ede1a2014-02-14 16:41:27 -050074const std::string DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
75
Jamie Madill5f562732014-02-14 16:41:24 -050076DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
77 : mRenderer(renderer)
78{
79}
80
81// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
82// Returns the number of used varying registers, or -1 if unsuccesful
83int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader)
84{
85 const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
86
87 fragmentShader->resetVaryingsRegisterAssignment();
88
89 for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
90 {
91 sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
92 GLenum transposedType = TransposeMatrixType(varying->type);
93
94 // matrices within varying structs are not transposed
95 int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
96 int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
97 bool success = false;
98
99 if (elements == 2 || elements == 3 || elements == 4)
100 {
101 for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
102 {
103 bool available = true;
104
105 for (int y = 0; y < registers && available; y++)
106 {
107 for (int x = 0; x < elements && available; x++)
108 {
109 if (packing[r + y][x])
110 {
111 available = false;
112 }
113 }
114 }
115
116 if (available)
117 {
118 varying->registerIndex = r;
119 varying->elementIndex = 0;
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 success = true;
130 }
131 }
132
133 if (!success && elements == 2)
134 {
135 for (int r = maxVaryingVectors - registers; r >= 0 && !success; 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 varying->elementIndex = 2;
154
155 for (int y = 0; y < registers; y++)
156 {
157 for (int x = 2; x < 4; x++)
158 {
159 packing[r + y][x] = &*varying;
160 }
161 }
162
163 success = true;
164 }
165 }
166 }
167 }
168 else if (elements == 1)
169 {
170 int space[4] = {0};
171
172 for (int y = 0; y < maxVaryingVectors; y++)
173 {
174 for (int x = 0; x < 4; x++)
175 {
176 space[x] += packing[y][x] ? 0 : 1;
177 }
178 }
179
180 int column = 0;
181
182 for (int x = 0; x < 4; x++)
183 {
184 if (space[x] >= registers && space[x] < space[column])
185 {
186 column = x;
187 }
188 }
189
190 if (space[column] >= registers)
191 {
192 for (int r = 0; r < maxVaryingVectors; r++)
193 {
194 if (!packing[r][column])
195 {
196 varying->registerIndex = r;
197
198 for (int y = r; y < r + registers; y++)
199 {
200 packing[y][column] = &*varying;
201 }
202
203 break;
204 }
205 }
206
207 varying->elementIndex = column;
208
209 success = true;
210 }
211 }
212 else UNREACHABLE();
213
214 if (!success)
215 {
216 infoLog.append("Could not pack varying %s", varying->name.c_str());
217
218 return -1;
219 }
220 }
221
222 // Return the number of used registers
223 int registers = 0;
224
225 for (int r = 0; r < maxVaryingVectors; r++)
226 {
227 if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
228 {
229 registers++;
230 }
231 }
232
233 return registers;
234}
235
236std::string DynamicHLSL::generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const
237{
238 std::string varyingHLSL;
239
240 for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
241 {
242 sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
243 if (varying->registerAssigned())
244 {
245 for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
246 {
247 GLenum transposedType = TransposeMatrixType(varying->type);
248 int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
249 for (int row = 0; row < variableRows; row++)
250 {
251 switch (varying->interpolation)
252 {
253 case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break;
254 case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break;
255 case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break;
256 default: UNREACHABLE();
257 }
258
259 std::string n = Str(varying->registerIndex + elementIndex * variableRows + row);
260
261 // matrices within structs are not transposed, hence we do not use the special struct prefix "rm"
262 std::string typeString = varying->isStruct() ? "_" + varying->structName :
263 gl_d3d::TypeString(UniformComponentType(transposedType)) + Str(VariableColumnCount(transposedType));
264
265 varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
266 }
267 }
268 }
269 else UNREACHABLE();
270 }
271
272 return varyingHLSL;
273}
274
Jamie Madillc5ede1a2014-02-14 16:41:27 -0500275std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[], const sh::Attribute shaderAttributes[]) const
276{
277 std::string vertexHLSL;
278
279 vertexHLSL += "struct VS_INPUT\n"
280 "{\n";
281
282 int semanticIndex = 0;
283 for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
284 {
285 const sh::Attribute &attribute = shaderAttributes[attributeIndex];
286
287 if (!attribute.name.empty())
288 {
289 vertexHLSL += " " + gl_d3d::TypeString(TransposeMatrixType(attribute.type)) + " ";
290 vertexHLSL += decorateAttribute(attribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n";
291
292 semanticIndex += AttributeRegisterCount(attribute.type);
293 }
294 }
295
296 vertexHLSL += "};\n"
297 "\n"
298 "void initAttributes(VS_INPUT input)\n"
299 "{\n";
300
301 for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
302 {
303 const sh::ShaderVariable &attribute = shaderAttributes[attributeIndex];
304
305 if (!attribute.name.empty())
306 {
307 vertexHLSL += " " + decorateAttribute(attribute.name) + " = ";
308 vertexHLSL += generateAttributeConversionHLSL(inputLayout[attributeIndex], attribute);
309 vertexHLSL += "(input." + decorateAttribute(attribute.name) + ");\n";
310 }
311 }
312
313 vertexHLSL += "}\n";
314
315 return vertexHLSL;
316}
317
Jamie Madill5f562732014-02-14 16:41:24 -0500318bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
319 std::string& pixelHLSL, std::string& vertexHLSL,
320 FragmentShader *fragmentShader, VertexShader *vertexShader,
321 std::map<int, VariableLocation> *programOutputVars) const
322{
323 if (pixelHLSL.empty() || vertexHLSL.empty())
324 {
325 return false;
326 }
327
328 bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
329 bool usesFragColor = fragmentShader->mUsesFragColor;
330 bool usesFragData = fragmentShader->mUsesFragData;
331 if (usesFragColor && usesFragData)
332 {
333 infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
334 return false;
335 }
336
337 // Write the HLSL input/output declarations
338 const int shaderModel = mRenderer->getMajorShaderModel();
339 const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
340
341 const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
342
343 // Two cases when writing to gl_FragColor and using ESSL 1.0:
344 // - with a 3.0 context, the output color is copied to channel 0
345 // - with a 2.0 context, the output color is broadcast to all channels
346 const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
347 const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
348
349 int shaderVersion = vertexShader->getShaderVersion();
350
351 if (registersNeeded > maxVaryingVectors)
352 {
353 infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
354
355 return false;
356 }
357
358 std::string varyingSemantic = (vertexShader->mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
359 std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
360 std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
361 std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
362
363 std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
364
365 // special varyings that use reserved registers
366 int reservedRegisterIndex = registers;
367 std::string fragCoordSemantic;
368 std::string pointCoordSemantic;
369
370 if (fragmentShader->mUsesFragCoord)
371 {
372 fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
373 }
374
375 if (fragmentShader->mUsesPointCoord)
376 {
377 // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
378 // In DX11 we compute this in the GS.
379 if (shaderModel == 3)
380 {
381 pointCoordSemantic = "TEXCOORD0";
382 }
383 else if (shaderModel >= 4)
384 {
385 pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
386 }
387 }
388
Jamie Madillc5ede1a2014-02-14 16:41:27 -0500389 // Add stub string to be replaced when shader is dynamically defined by its layout
390 vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n";
Jamie Madill5f562732014-02-14 16:41:24 -0500391
Jamie Madillc5ede1a2014-02-14 16:41:27 -0500392 vertexHLSL += "struct VS_OUTPUT\n"
Jamie Madill5f562732014-02-14 16:41:24 -0500393 "{\n";
394
395 if (shaderModel < 4)
396 {
397 vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
398 }
399
400 vertexHLSL += varyingHLSL;
401
402 if (fragmentShader->mUsesFragCoord)
403 {
404 vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
405 }
406
407 if (vertexShader->mUsesPointSize && shaderModel >= 3)
408 {
409 vertexHLSL += " float gl_PointSize : PSIZE;\n";
410 }
411
412 if (shaderModel >= 4)
413 {
414 vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
415 }
416
417 vertexHLSL += "};\n"
418 "\n"
419 "VS_OUTPUT main(VS_INPUT input)\n"
Jamie Madillc5ede1a2014-02-14 16:41:27 -0500420 "{\n"
421 " initAttributes(input);\n";
Jamie Madill5f562732014-02-14 16:41:24 -0500422
423 if (shaderModel >= 4)
424 {
425 vertexHLSL += "\n"
426 " gl_main();\n"
427 "\n"
428 " VS_OUTPUT output;\n"
429 " output.gl_Position.x = gl_Position.x;\n"
430 " output.gl_Position.y = -gl_Position.y;\n"
431 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
432 " output.gl_Position.w = gl_Position.w;\n";
433 }
434 else
435 {
436 vertexHLSL += "\n"
437 " gl_main();\n"
438 "\n"
439 " VS_OUTPUT output;\n"
440 " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
441 " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
442 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
443 " output.gl_Position.w = gl_Position.w;\n";
444 }
445
446 if (vertexShader->mUsesPointSize && shaderModel >= 3)
447 {
448 vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
449 }
450
451 if (fragmentShader->mUsesFragCoord)
452 {
453 vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
454 }
455
456 for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++)
457 {
458 sh::Varying *varying = &vertexShader->mVaryings[vertVaryingIndex];
459 if (varying->registerAssigned())
460 {
461 for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
462 {
463 int variableRows = (varying->isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying->type)));
464
465 for (int row = 0; row < variableRows; row++)
466 {
467 int r = varying->registerIndex + elementIndex * variableRows + row;
468 vertexHLSL += " output.v" + Str(r);
469
470 bool sharedRegister = false; // Register used by multiple varyings
471
472 for (int x = 0; x < 4; x++)
473 {
474 if (packing[r][x] && packing[r][x] != packing[r][0])
475 {
476 sharedRegister = true;
477 break;
478 }
479 }
480
481 if(sharedRegister)
482 {
483 vertexHLSL += ".";
484
485 for (int x = 0; x < 4; x++)
486 {
487 if (packing[r][x] == &*varying)
488 {
489 switch(x)
490 {
491 case 0: vertexHLSL += "x"; break;
492 case 1: vertexHLSL += "y"; break;
493 case 2: vertexHLSL += "z"; break;
494 case 3: vertexHLSL += "w"; break;
495 }
496 }
497 }
498 }
499
500 vertexHLSL += " = _" + varying->name;
501
502 if (varying->isArray())
503 {
504 vertexHLSL += ArrayString(elementIndex);
505 }
506
507 if (variableRows > 1)
508 {
509 vertexHLSL += ArrayString(row);
510 }
511
512 vertexHLSL += ";\n";
513 }
514 }
515 }
516 }
517
518 vertexHLSL += "\n"
519 " return output;\n"
520 "}\n";
521
522 pixelHLSL += "struct PS_INPUT\n"
523 "{\n";
524
525 pixelHLSL += varyingHLSL;
526
527 if (fragmentShader->mUsesFragCoord)
528 {
529 pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
530 }
531
532 if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
533 {
534 pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
535 }
536
537 // Must consume the PSIZE element if the geometry shader is not active
538 // We won't know if we use a GS until we draw
539 if (vertexShader->mUsesPointSize && shaderModel >= 4)
540 {
541 pixelHLSL += " float gl_PointSize : PSIZE;\n";
542 }
543
544 if (fragmentShader->mUsesFragCoord)
545 {
546 if (shaderModel >= 4)
547 {
548 pixelHLSL += " float4 dx_VPos : SV_Position;\n";
549 }
550 else if (shaderModel >= 3)
551 {
552 pixelHLSL += " float2 dx_VPos : VPOS;\n";
553 }
554 }
555
556 pixelHLSL += "};\n"
557 "\n"
558 "struct PS_OUTPUT\n"
559 "{\n";
560
561 if (shaderVersion < 300)
562 {
563 for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
564 {
565 pixelHLSL += " float4 gl_Color" + Str(renderTargetIndex) + " : " + targetSemantic + Str(renderTargetIndex) + ";\n";
566 }
567
568 if (fragmentShader->mUsesFragDepth)
569 {
570 pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
571 }
572 }
573 else
574 {
575 defineOutputVariables(fragmentShader, programOutputVars);
576
577 const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getOutputVariables();
578 for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
579 {
580 const VariableLocation &outputLocation = locationIt->second;
581 const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
582 const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
583
584 pixelHLSL += " " + gl_d3d::TypeString(outputVariable.type) +
585 " out_" + outputLocation.name + elementString +
586 " : " + targetSemantic + Str(locationIt->first) + ";\n";
587 }
588 }
589
590 pixelHLSL += "};\n"
591 "\n";
592
593 if (fragmentShader->mUsesFrontFacing)
594 {
595 if (shaderModel >= 4)
596 {
597 pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
598 "{\n";
599 }
600 else
601 {
602 pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
603 "{\n";
604 }
605 }
606 else
607 {
608 pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
609 "{\n";
610 }
611
612 if (fragmentShader->mUsesFragCoord)
613 {
614 pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
615
616 if (shaderModel >= 4)
617 {
618 pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
619 " gl_FragCoord.y = input.dx_VPos.y;\n";
620 }
621 else if (shaderModel >= 3)
622 {
623 pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
624 " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
625 }
626 else
627 {
628 // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
629 pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
630 " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
631 }
632
633 pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
634 " gl_FragCoord.w = rhw;\n";
635 }
636
637 if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
638 {
639 pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
640 pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
641 }
642
643 if (fragmentShader->mUsesFrontFacing)
644 {
645 if (shaderModel <= 3)
646 {
647 pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
648 }
649 else
650 {
651 pixelHLSL += " gl_FrontFacing = isFrontFace;\n";
652 }
653 }
654
655 for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
656 {
657 sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
658 if (varying->registerAssigned())
659 {
660 for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
661 {
662 GLenum transposedType = TransposeMatrixType(varying->type);
663 int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
664 for (int row = 0; row < variableRows; row++)
665 {
666 std::string n = Str(varying->registerIndex + elementIndex * variableRows + row);
667 pixelHLSL += " _" + varying->name;
668
669 if (varying->isArray())
670 {
671 pixelHLSL += ArrayString(elementIndex);
672 }
673
674 if (variableRows > 1)
675 {
676 pixelHLSL += ArrayString(row);
677 }
678
679 if (varying->isStruct())
680 {
681 pixelHLSL += " = input.v" + n + ";\n"; break;
682 }
683 else
684 {
685 switch (VariableColumnCount(transposedType))
686 {
687 case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break;
688 case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break;
689 case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
690 case 4: pixelHLSL += " = input.v" + n + ";\n"; break;
691 default: UNREACHABLE();
692 }
693 }
694 }
695 }
696 }
697 else UNREACHABLE();
698 }
699
700 pixelHLSL += "\n"
701 " gl_main();\n"
702 "\n"
703 " PS_OUTPUT output;\n";
704
705 if (shaderVersion < 300)
706 {
707 for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
708 {
709 unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
710
711 pixelHLSL += " output.gl_Color" + Str(renderTargetIndex) + " = gl_Color[" + Str(sourceColorIndex) + "];\n";
712 }
713
714 if (fragmentShader->mUsesFragDepth)
715 {
716 pixelHLSL += " output.gl_Depth = gl_Depth;\n";
717 }
718 }
719 else
720 {
721 for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
722 {
723 const VariableLocation &outputLocation = locationIt->second;
724 const std::string &variableName = "out_" + outputLocation.name;
725 const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
726 const std::string &staticVariableName = variableName + ArrayString(outputLocation.element);
727
728 pixelHLSL += " output." + outVariableName + " = " + staticVariableName + ";\n";
729 }
730 }
731
732 pixelHLSL += "\n"
733 " return output;\n"
734 "}\n";
735
736 return true;
737}
738
739void DynamicHLSL::defineOutputVariables(FragmentShader *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
740{
741 const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getOutputVariables();
742
743 for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++)
744 {
745 const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
746 const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
747
748 if (outputVariable.arraySize > 0)
749 {
750 for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
751 {
752 const int location = baseLocation + elementIndex;
753 ASSERT(programOutputVars->count(location) == 0);
754 (*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
755 }
756 }
757 else
758 {
759 ASSERT(programOutputVars->count(baseLocation) == 0);
760 (*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
761 }
762 }
763}
764
765std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
766{
767 // for now we only handle point sprite emulation
768 ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
769 return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader);
770}
771
772std::string DynamicHLSL::generatePointSpriteHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
773{
774 ASSERT(registers >= 0);
775 ASSERT(vertexShader->mUsesPointSize);
776 ASSERT(mRenderer->getMajorShaderModel() >= 4);
777
778 std::string geomHLSL;
779
780 std::string varyingSemantic = "TEXCOORD";
781
782 std::string fragCoordSemantic;
783 std::string pointCoordSemantic;
784
785 int reservedRegisterIndex = registers;
786
787 if (fragmentShader->mUsesFragCoord)
788 {
789 fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
790 }
791
792 if (fragmentShader->mUsesPointCoord)
793 {
794 pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
795 }
796
797 geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
798 "\n"
799 "struct GS_INPUT\n"
800 "{\n";
801
802 std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
803
804 geomHLSL += varyingHLSL;
805
806 if (fragmentShader->mUsesFragCoord)
807 {
808 geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
809 }
810
811 geomHLSL += " float gl_PointSize : PSIZE;\n"
812 " float4 gl_Position : SV_Position;\n"
813 "};\n"
814 "\n"
815 "struct GS_OUTPUT\n"
816 "{\n";
817
818 geomHLSL += varyingHLSL;
819
820 if (fragmentShader->mUsesFragCoord)
821 {
822 geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
823 }
824
825 if (fragmentShader->mUsesPointCoord)
826 {
827 geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
828 }
829
830 geomHLSL += " float gl_PointSize : PSIZE;\n"
831 " float4 gl_Position : SV_Position;\n"
832 "};\n"
833 "\n"
834 "static float2 pointSpriteCorners[] = \n"
835 "{\n"
836 " float2( 0.5f, -0.5f),\n"
837 " float2( 0.5f, 0.5f),\n"
838 " float2(-0.5f, -0.5f),\n"
839 " float2(-0.5f, 0.5f)\n"
840 "};\n"
841 "\n"
842 "static float2 pointSpriteTexcoords[] = \n"
843 "{\n"
844 " float2(1.0f, 1.0f),\n"
845 " float2(1.0f, 0.0f),\n"
846 " float2(0.0f, 1.0f),\n"
847 " float2(0.0f, 0.0f)\n"
848 "};\n"
849 "\n"
850 "static float minPointSize = " + Str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
851 "static float maxPointSize = " + Str(mRenderer->getMaxPointSize()) + ".0f;\n"
852 "\n"
853 "[maxvertexcount(4)]\n"
854 "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
855 "{\n"
856 " GS_OUTPUT output = (GS_OUTPUT)0;\n"
857 " output.gl_PointSize = input[0].gl_PointSize;\n";
858
859 for (int r = 0; r < registers; r++)
860 {
861 geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n";
862 }
863
864 if (fragmentShader->mUsesFragCoord)
865 {
866 geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n";
867 }
868
869 geomHLSL += " \n"
870 " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
871 " float4 gl_Position = input[0].gl_Position;\n"
872 " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
873
874 for (int corner = 0; corner < 4; corner++)
875 {
876 geomHLSL += " \n"
877 " output.gl_Position = gl_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
878
879 if (fragmentShader->mUsesPointCoord)
880 {
881 geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n";
882 }
883
884 geomHLSL += " outStream.Append(output);\n";
885 }
886
887 geomHLSL += " \n"
888 " outStream.RestartStrip();\n"
889 "}\n";
890
891 return geomHLSL;
892}
893
894// This method needs to match OutputHLSL::decorate
895std::string DynamicHLSL::decorateAttribute(const std::string &name)
896{
897 if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
898 {
899 return "_" + name;
900 }
901
902 return name;
903}
904
Jamie Madillc5ede1a2014-02-14 16:41:27 -0500905std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const
906{
907 // Matrix
908 if (IsMatrixType(shaderAttrib.type))
909 {
910 return "transpose";
911 }
912
913 // TODO: un-normalized integer data
914
915 // No conversion necessary
916 return "";
917}
918
Jamie Madill5f562732014-02-14 16:41:24 -0500919}