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.
6
// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
9
#include "libANGLE/renderer/d3d/DynamicHLSL.h"
11
#include "common/utilities.h"
12
#include "compiler/translator/blocklayoutHLSL.h"
13
#include "libANGLE/Program.h"
14
#include "libANGLE/Shader.h"
15
#include "libANGLE/formatutils.h"
16
#include "libANGLE/renderer/d3d/ProgramD3D.h"
17
#include "libANGLE/renderer/d3d/RendererD3D.h"
18
#include "libANGLE/renderer/d3d/ShaderD3D.h"
19
#include "libANGLE/renderer/d3d/VaryingPacking.h"
29
std::string HLSLComponentTypeString(GLenum componentType)
31
switch (componentType)
37
case GL_UNSIGNED_NORMALIZED:
38
case GL_SIGNED_NORMALIZED:
43
return "not-component-type";
47
std::string HLSLComponentTypeString(GLenum componentType, int componentCount)
49
return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : "");
52
std::string HLSLMatrixTypeString(GLenum type)
76
return "not-matrix-type";
80
std::string HLSLTypeString(GLenum type)
82
if (gl::IsMatrixType(type))
84
return HLSLMatrixTypeString(type);
87
return HLSLComponentTypeString(gl::VariableComponentType(type),
88
gl::VariableComponentCount(type));
91
const PixelShaderOutputVariable *FindOutputAtLocation(
92
const std::vector<PixelShaderOutputVariable> &outputVariables,
93
unsigned int location)
95
for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
97
if (outputVariables[variableIndex].outputIndex == location)
99
return &outputVariables[variableIndex];
106
void WriteArrayString(std::stringstream &strstr, unsigned int i)
108
static_assert(GL_INVALID_INDEX == UINT_MAX,
109
"GL_INVALID_INDEX must be equal to the max unsigned int.");
120
const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
121
const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
122
} // anonymous namespace
124
std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
126
// SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
127
// In D3D11 we manually compute gl_PointCoord in the GS.
128
return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
131
// DynamicHLSL implementation
133
DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
137
void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking,
138
std::stringstream &hlslStream) const
140
std::string varyingSemantic =
141
GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize());
143
for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList())
145
const auto &varying = *registerInfo.packedVarying->varying;
146
ASSERT(!varying.isStruct());
148
// TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
149
// registers being used.
150
// For example, if there are N registers, and we have N vec3 varyings and 1 float
151
// varying, then D3D will pack them into N registers.
152
// If the float varying has the 'nointerpolation' modifier on it then we would need
153
// N + 1 registers, and D3D compilation will fail.
155
switch (registerInfo.packedVarying->interpolation)
157
case sh::INTERPOLATION_SMOOTH:
160
case sh::INTERPOLATION_FLAT:
161
hlslStream << " nointerpolation ";
163
case sh::INTERPOLATION_CENTROID:
164
hlslStream << " centroid ";
170
GLenum transposedType = gl::TransposeMatrixType(varying.type);
171
GLenum componentType = gl::VariableComponentType(transposedType);
172
int columnCount = gl::VariableColumnCount(transposedType);
173
hlslStream << HLSLComponentTypeString(componentType, columnCount);
174
unsigned int semanticIndex = registerInfo.semanticIndex;
175
hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
179
std::string DynamicHLSL::generateVertexShaderForInputLayout(
180
const std::string &sourceShader,
181
const InputLayout &inputLayout,
182
const std::vector<sh::Attribute> &shaderAttributes) const
184
std::stringstream structStream;
185
std::stringstream initStream;
187
structStream << "struct VS_INPUT\n"
190
int semanticIndex = 0;
191
unsigned int inputIndex = 0;
193
// If gl_PointSize is used in the shader then pointsprites rendering is expected.
194
// If the renderer does not support Geometry shaders then Instanced PointSprite emulation
196
bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos;
197
bool useInstancedPointSpriteEmulation =
198
usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
200
// Instanced PointSprite emulation requires additional entries in the
201
// VS_INPUT structure to support the vertices that make up the quad vertices.
202
// These values must be in sync with the cooresponding values added during inputlayout creation
203
// in InputLayoutCache::applyVertexBuffers().
205
// The additional entries must appear first in the VS_INPUT layout because
206
// Windows Phone 8 era devices require per vertex data to physically come
207
// before per instance data in the shader.
208
if (useInstancedPointSpriteEmulation)
210
structStream << " float3 spriteVertexPos : SPRITEPOSITION0;\n"
211
<< " float2 spriteTexCoord : SPRITETEXCOORD0;\n";
214
for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex)
216
const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex];
217
if (!shaderAttribute.name.empty())
219
ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
220
VertexFormatType vertexFormatType =
221
inputIndex < inputLayout.size() ? inputLayout[inputIndex] : VERTEX_FORMAT_INVALID;
223
// HLSL code for input structure
224
if (IsMatrixType(shaderAttribute.type))
226
// Matrix types are always transposed
228
<< HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
232
GLenum componentType = mRenderer->getVertexComponentType(vertexFormatType);
234
if (shaderAttribute.name == "gl_InstanceID")
236
// The input type of the instance ID in HLSL (uint) differs from the one in ESSL
238
structStream << " uint";
242
structStream << " " << HLSLComponentTypeString(
244
VariableComponentCount(shaderAttribute.type));
248
structStream << " " << decorateVariable(shaderAttribute.name) << " : ";
250
if (shaderAttribute.name == "gl_InstanceID")
252
structStream << "SV_InstanceID";
256
structStream << "TEXCOORD" << semanticIndex;
257
semanticIndex += VariableRegisterCount(shaderAttribute.type);
260
structStream << ";\n";
262
// HLSL code for initialization
263
initStream << " " << decorateVariable(shaderAttribute.name) << " = ";
265
// Mismatched vertex attribute to vertex input may result in an undefined
266
// data reinterpretation (eg for pure integer->float, float->pure integer)
267
// TODO: issue warning with gl debug info extension, when supported
268
if (IsMatrixType(shaderAttribute.type) ||
269
(mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0)
271
initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute);
275
initStream << "input." << decorateVariable(shaderAttribute.name);
280
inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
284
structStream << "};\n"
286
"void initAttributes(VS_INPUT input)\n"
288
<< initStream.str() << "}\n";
290
std::string vertexHLSL(sourceShader);
292
size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
293
vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), structStream.str());
298
std::string DynamicHLSL::generatePixelShaderForOutputSignature(
299
const std::string &sourceShader,
300
const std::vector<PixelShaderOutputVariable> &outputVariables,
302
const std::vector<GLenum> &outputLayout) const
304
const int shaderModel = mRenderer->getMajorShaderModel();
305
std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
306
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
308
std::stringstream declarationStream;
309
std::stringstream copyStream;
311
declarationStream << "struct PS_OUTPUT\n"
314
for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex)
316
GLenum binding = outputLayout[layoutIndex];
318
if (binding != GL_NONE)
320
unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
322
const PixelShaderOutputVariable *outputVariable =
323
FindOutputAtLocation(outputVariables, location);
325
// OpenGL ES 3.0 spec $4.2.1
326
// If [...] not all user-defined output variables are written, the values of fragment
328
// corresponding to unwritten variables are similarly undefined.
331
declarationStream << " " + HLSLTypeString(outputVariable->type) << " "
332
<< outputVariable->name << " : " << targetSemantic
333
<< static_cast<int>(layoutIndex) << ";\n";
335
copyStream << " output." << outputVariable->name << " = "
336
<< outputVariable->source << ";\n";
343
declarationStream << " float gl_Depth : " << depthSemantic << ";\n";
344
copyStream << " output.gl_Depth = gl_Depth; \n";
347
declarationStream << "};\n"
349
"PS_OUTPUT generateOutput()\n"
351
" PS_OUTPUT output;\n"
352
<< copyStream.str() << " return output;\n"
355
std::string pixelHLSL(sourceShader);
357
size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
358
pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(),
359
declarationStream.str());
364
void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType,
365
const VaryingPacking &varyingPacking,
366
std::stringstream &linkStream) const
368
const auto &builtins = varyingPacking.builtins(shaderType);
369
ASSERT(builtins.dxPosition.enabled);
371
<< " float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
373
if (builtins.glPosition.enabled)
375
linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n";
378
if (builtins.glFragCoord.enabled)
380
linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
383
if (builtins.glPointCoord.enabled)
385
linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
388
if (builtins.glPointSize.enabled)
390
linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
393
// Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the
395
generateVaryingHLSL(varyingPacking, linkStream);
397
linkStream << "};\n";
400
bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
401
const gl::Program::Data &programData,
402
const ProgramD3DMetadata &programMetadata,
403
const VaryingPacking &varyingPacking,
404
std::string *pixelHLSL,
405
std::string *vertexHLSL) const
407
ASSERT(pixelHLSL->empty() && vertexHLSL->empty());
409
const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader();
410
const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(vertexShaderGL);
411
const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader();
412
const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL);
413
const int shaderModel = mRenderer->getMajorShaderModel();
415
// usesViewScale() isn't supported in the D3D9 renderer
416
ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale());
418
bool useInstancedPointSpriteEmulation =
419
programMetadata.usesPointSize() &&
420
mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
422
// Validation done in the compiler
423
ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
425
std::stringstream vertexStream;
426
vertexStream << vertexShaderGL->getTranslatedSource();
428
// Instanced PointSprite emulation requires additional entries originally generated in the
429
// GeometryShader HLSL. These include pointsize clamp values.
430
if (useInstancedPointSpriteEmulation)
432
vertexStream << "static float minPointSize = "
433
<< static_cast<int>(data.caps->minAliasedPointSize) << ".0f;\n"
434
<< "static float maxPointSize = "
435
<< static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n";
438
// Add stub string to be replaced when shader is dynamically defined by its layout
439
vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n";
441
// Write the HLSL input/output declarations
442
vertexStream << "struct VS_OUTPUT\n";
443
generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream);
445
<< "VS_OUTPUT main(VS_INPUT input)\n"
447
<< " initAttributes(input);\n";
449
if (vertexShader->usesDeferredInit())
452
<< " initializeDeferredGlobals();\n";
458
<< " VS_OUTPUT output;\n";
460
const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX);
462
if (vertexBuiltins.glPosition.enabled)
464
vertexStream << " output.gl_Position = gl_Position;\n";
467
// On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
468
if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
470
vertexStream << " output.dx_Position.x = gl_Position.x;\n";
472
if (programMetadata.usesViewScale())
474
// This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f
475
// when rendering to the default framebuffer. No other values are valid.
476
vertexStream << " output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n";
480
vertexStream << " output.dx_Position.y = - gl_Position.y;\n";
483
vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
484
<< " output.dx_Position.w = gl_Position.w;\n";
488
vertexStream << " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + "
489
"dx_ViewAdjust.x * gl_Position.w;\n";
491
// If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*,
492
// then we need to multiply the gl_Position.y by the viewScale.
493
// usesViewScale() isn't supported when using the D3D9 renderer.
494
if (programMetadata.usesViewScale() &&
495
(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != ""))
497
vertexStream << " output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * "
498
"dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n";
502
vertexStream << " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + "
503
"dx_ViewAdjust.y * gl_Position.w);\n";
506
vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
507
<< " output.dx_Position.w = gl_Position.w;\n";
510
// We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
511
if (vertexBuiltins.glPointSize.enabled)
513
vertexStream << " output.gl_PointSize = gl_PointSize;\n";
516
if (vertexBuiltins.glFragCoord.enabled)
518
vertexStream << " output.gl_FragCoord = gl_Position;\n";
521
for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList())
523
const auto &packedVarying = *registerInfo.packedVarying;
524
const auto &varying = *packedVarying.varying;
525
ASSERT(!varying.isStruct());
527
vertexStream << " output.v" << registerInfo.semanticIndex << " = ";
529
if (packedVarying.isStructField())
531
vertexStream << decorateVariable(packedVarying.parentStructName) << ".";
534
vertexStream << decorateVariable(varying.name);
536
if (varying.isArray())
538
WriteArrayString(vertexStream, registerInfo.varyingArrayIndex);
541
if (VariableRowCount(varying.type) > 1)
543
WriteArrayString(vertexStream, registerInfo.varyingRowIndex);
546
vertexStream << ";\n";
549
// Instanced PointSprite emulation requires additional entries to calculate
550
// the final output vertex positions of the quad that represents each sprite.
551
if (useInstancedPointSpriteEmulation)
554
<< " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n";
556
vertexStream << " output.dx_Position.x += (input.spriteVertexPos.x * gl_PointSize / "
557
"(dx_ViewCoords.x*2)) * output.dx_Position.w;";
559
if (programMetadata.usesViewScale())
561
// Multiply by ViewScale to invert the rendering when appropriate
562
vertexStream << " output.dx_Position.y += (-dx_ViewScale.y * "
563
"input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2)) * "
564
"output.dx_Position.w;";
568
vertexStream << " output.dx_Position.y += (input.spriteVertexPos.y * gl_PointSize / "
569
"(dx_ViewCoords.y*2)) * output.dx_Position.w;";
573
<< " output.dx_Position.z += input.spriteVertexPos.z * output.dx_Position.w;\n";
575
if (programMetadata.usesPointCoord())
578
<< " output.gl_PointCoord = input.spriteTexCoord;\n";
582
// Renderers that enable instanced pointsprite emulation require the vertex shader output member
583
// gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same
584
// default value used in the generated pixel shader.
585
if (programMetadata.usesInsertedPointCoordValue())
587
ASSERT(!useInstancedPointSpriteEmulation);
589
<< " output.gl_PointCoord = float2(0.5, 0.5);\n";
593
<< " return output;\n"
596
std::stringstream pixelStream;
597
pixelStream << fragmentShaderGL->getTranslatedSource();
598
pixelStream << "struct PS_INPUT\n";
599
generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream);
602
pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n";
604
if (fragmentShader->usesFrontFacing())
606
if (shaderModel >= 4)
608
pixelStream << "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
613
pixelStream << "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
619
pixelStream << "PS_OUTPUT main(PS_INPUT input)\n"
623
const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL);
625
if (pixelBuiltins.glFragCoord.enabled)
627
pixelStream << " float rhw = 1.0 / input.gl_FragCoord.w;\n";
629
// Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
630
// Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using
632
if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
634
pixelStream << " gl_FragCoord.x = input.dx_Position.x;\n"
635
<< " gl_FragCoord.y = input.dx_Position.y;\n";
637
else if (shaderModel == 3)
639
pixelStream << " gl_FragCoord.x = input.dx_Position.x + 0.5;\n"
640
<< " gl_FragCoord.y = input.dx_Position.y + 0.5;\n";
644
// dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See
645
// Renderer::setViewport()
646
pixelStream << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + "
648
<< " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + "
649
"dx_ViewCoords.w;\n";
652
if (programMetadata.usesViewScale())
654
// For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account
655
// for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using
656
// dx_ViewCoords and is always correct irrespective of dx_ViewScale's value.
657
// NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+).
658
if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
661
// - dx_ViewScale.y = -1.0f when rendering to texture
662
// - dx_ViewScale.y = +1.0f when rendering to the default framebuffer
663
// - gl_FragCoord.y has been set correctly above.
665
// When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate.
666
// This involves subtracting the y coordinate from the height of the area being
669
// First we calculate the height of the area being rendered to:
670
// render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) *
673
// Note that when we're rendering to default FB, we want our output to be
675
// "gl_FragCoord.y = render_area_height - gl_FragCoord.y"
677
// When we're rendering to a texture, we want our output to be equivalent to:
678
// "gl_FragCoord.y = gl_FragCoord.y;"
680
// If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that
681
// - When rendering to default FB: scale_factor = 1.0f
682
// - When rendering to texture: scale_factor = 0.0f
684
// Therefore, we can get our desired output by setting:
685
// "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y *
688
// Simplifying, this becomes:
690
<< " gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /"
691
"(1.0f - input.gl_FragCoord.y * rhw) - dx_ViewScale.y * gl_FragCoord.y;\n";
695
pixelStream << " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + "
697
<< " gl_FragCoord.w = rhw;\n";
700
if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3)
702
pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n"
703
<< " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
706
if (fragmentShader->usesFrontFacing())
708
if (shaderModel <= 3)
710
pixelStream << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
714
pixelStream << " gl_FrontFacing = isFrontFace;\n";
718
for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList())
720
const auto &packedVarying = *registerInfo.packedVarying;
721
const auto &varying = *packedVarying.varying;
722
ASSERT(!varying.isBuiltIn() && !varying.isStruct());
724
// Don't reference VS-only transform feedback varyings in the PS.
725
if (registerInfo.packedVarying->vertexOnly)
730
if (packedVarying.isStructField())
732
pixelStream << decorateVariable(packedVarying.parentStructName) << ".";
735
pixelStream << decorateVariable(varying.name);
737
if (varying.isArray())
739
WriteArrayString(pixelStream, registerInfo.varyingArrayIndex);
742
GLenum transposedType = TransposeMatrixType(varying.type);
743
if (VariableRowCount(transposedType) > 1)
745
WriteArrayString(pixelStream, registerInfo.varyingRowIndex);
748
pixelStream << " = input.v" << registerInfo.semanticIndex;
750
switch (VariableColumnCount(transposedType))
756
pixelStream << ".xy";
759
pixelStream << ".xyz";
766
pixelStream << ";\n";
769
if (fragmentShader->usesDeferredInit())
772
<< " initializeDeferredGlobals();\n";
778
<< " return generateOutput();\n"
781
*vertexHLSL = vertexStream.str();
782
*pixelHLSL = pixelStream.str();
787
std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const
789
ASSERT(mRenderer->getMajorShaderModel() >= 4);
791
std::stringstream preambleStream;
793
const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
795
preambleStream << "struct GS_INPUT\n";
796
generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream);
797
preambleStream << "\n"
798
<< "struct GS_OUTPUT\n";
799
generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream);
802
<< "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
804
<< " output.gl_Position = input.gl_Position;\n";
806
if (builtins.glPointSize.enabled)
808
preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
811
for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList())
813
preambleStream << " output.v" << varyingRegister.semanticIndex << " = ";
814
if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT)
816
preambleStream << "flat";
818
preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n";
821
if (builtins.glFragCoord.enabled)
823
preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n";
826
// Only write the dx_Position if we aren't using point sprites
827
preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n"
828
<< " output.dx_Position = input.dx_Position;\n"
829
<< "#endif // ANGLE_POINT_SPRITE_SHADER\n"
832
return preambleStream.str();
835
std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
836
const gl::Data &data,
837
const gl::Program::Data &programData,
838
const bool useViewScale,
839
const std::string &preambleString) const
841
ASSERT(mRenderer->getMajorShaderModel() >= 4);
843
std::stringstream shaderStream;
845
const bool pointSprites = (primitiveType == PRIMITIVE_POINTS);
846
const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
848
const char *inputPT = nullptr;
849
const char *outputPT = nullptr;
851
int maxVertexOutput = 0;
853
switch (primitiveType)
855
case PRIMITIVE_POINTS:
857
outputPT = "Triangle";
862
case PRIMITIVE_LINES:
863
case PRIMITIVE_LINE_STRIP:
864
case PRIMITIVE_LINE_LOOP:
871
case PRIMITIVE_TRIANGLES:
872
case PRIMITIVE_TRIANGLE_STRIP:
873
case PRIMITIVE_TRIANGLE_FAN:
874
inputPT = "triangle";
875
outputPT = "Triangle";
887
shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
889
"uniform float4 dx_ViewCoords : register(c1);\n";
893
shaderStream << "uniform float2 dx_ViewScale : register(c3);\n";
897
"static float2 pointSpriteCorners[] = \n"
899
" float2( 0.5f, -0.5f),\n"
900
" float2( 0.5f, 0.5f),\n"
901
" float2(-0.5f, -0.5f),\n"
902
" float2(-0.5f, 0.5f)\n"
905
"static float2 pointSpriteTexcoords[] = \n"
907
" float2(1.0f, 1.0f),\n"
908
" float2(1.0f, 0.0f),\n"
909
" float2(0.0f, 1.0f),\n"
910
" float2(0.0f, 0.0f)\n"
913
"static float minPointSize = "
914
<< static_cast<int>(data.caps->minAliasedPointSize)
916
"static float maxPointSize = "
917
<< static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n"
921
shaderStream << preambleString << "\n"
922
<< "[maxvertexcount(" << maxVertexOutput << ")]\n"
923
<< "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], ";
925
if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
927
shaderStream << "uint primitiveID : SV_PrimitiveID, ";
930
shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n"
932
<< " GS_OUTPUT output = (GS_OUTPUT)0;\n";
934
if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
936
shaderStream << " uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n";
940
shaderStream << " uint lastVertexIndex = " << (inputSize - 1) << ";\n";
943
for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex)
945
shaderStream << " copyVertex(output, input[" << vertexIndex
946
<< "], input[lastVertexIndex]);\n";
950
ASSERT(inputSize == maxVertexOutput);
951
shaderStream << " outStream.Append(output);\n";
958
" float4 dx_Position = input[0].dx_Position;\n"
959
" float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, "
961
" float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / "
962
"dx_ViewCoords.y) * dx_Position.w;\n";
964
for (int corner = 0; corner < 4; corner++)
968
shaderStream << " \n"
969
" output.dx_Position = dx_Position + float4(1.0f, "
970
"-dx_ViewScale.y, 1.0f, 1.0f)"
971
" * float4(pointSpriteCorners["
972
<< corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
977
" output.dx_Position = dx_Position + float4(pointSpriteCorners["
978
<< corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
983
shaderStream << " output.gl_PointCoord = pointSpriteTexcoords[" << corner
987
shaderStream << " outStream.Append(output);\n";
991
shaderStream << " \n"
992
" outStream.RestartStrip();\n"
995
return shaderStream.str();
998
// This method needs to match OutputHLSL::decorate
999
std::string DynamicHLSL::decorateVariable(const std::string &name)
1001
if (name.compare(0, 3, "gl_") != 0)
1009
std::string DynamicHLSL::generateAttributeConversionHLSL(
1010
gl::VertexFormatType vertexFormatType,
1011
const sh::ShaderVariable &shaderAttrib) const
1013
const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
1014
std::string attribString = "input." + decorateVariable(shaderAttrib.name);
1017
if (IsMatrixType(shaderAttrib.type))
1019
return "transpose(" + attribString + ")";
1022
GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
1023
int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
1025
// Perform integer to float conversion (if necessary)
1026
bool requiresTypeConversion =
1027
(shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT);
1029
if (requiresTypeConversion)
1031
// TODO: normalization for 32-bit integer formats
1032
ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger);
1033
return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
1036
// No conversion necessary
1037
return attribString;
1040
void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data,
1041
const gl::Program::Data &programData,
1042
const ProgramD3DMetadata &metadata,
1043
std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
1045
// Two cases when writing to gl_FragColor and using ESSL 1.0:
1046
// - with a 3.0 context, the output color is copied to channel 0
1047
// - with a 2.0 context, the output color is broadcast to all channels
1048
bool broadcast = metadata.usesBroadcast(data);
1049
const unsigned int numRenderTargets =
1050
(broadcast || metadata.usesMultipleFragmentOuts() ? data.caps->maxDrawBuffers : 1);
1052
if (metadata.getMajorShaderVersion() < 300)
1054
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
1055
renderTargetIndex++)
1057
PixelShaderOutputVariable outputKeyVariable;
1058
outputKeyVariable.type = GL_FLOAT_VEC4;
1059
outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
1060
outputKeyVariable.source =
1061
broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
1062
outputKeyVariable.outputIndex = renderTargetIndex;
1064
outPixelShaderKey->push_back(outputKeyVariable);
1069
const auto &shaderOutputVars =
1070
metadata.getFragmentShader()->getData().getActiveOutputVariables();
1072
for (auto outputPair : programData.getOutputVariables())
1074
const VariableLocation &outputLocation = outputPair.second;
1075
const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
1076
const std::string &variableName = "out_" + outputLocation.name;
1077
const std::string &elementString =
1078
(outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
1080
ASSERT(outputVariable.staticUse);
1082
PixelShaderOutputVariable outputKeyVariable;
1083
outputKeyVariable.type = outputVariable.type;
1084
outputKeyVariable.name = variableName + elementString;
1085
outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
1086
outputKeyVariable.outputIndex = outputPair.first;
1088
outPixelShaderKey->push_back(outputKeyVariable);