Commit 5f562735 by Jamie Madill

Moved all HLSL-related code from ProgramBinary to DynamicHLSL.

DynamicHLSL encapsulates all HLSL generation we need outside the the shader translator, such as for linking between input and output stages and point sprite geometry shaders. BUG=angle:560 Change-Id: Ib5079aa102000a7c37b166bcbe26b09cc82f8932 Reviewed-on: https://chromium-review.googlesource.com/185191Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e8bc3193
......@@ -140,16 +140,17 @@
<ClInclude Include="..\..\src\libGLESv2\Query.h"/>
<ClInclude Include="..\..\src\libGLESv2\ResourceManager.h"/>
<ClInclude Include="..\..\src\libGLESv2\Texture.h"/>
<ClInclude Include="..\..\src\libGLESv2\DynamicHLSL.h"/>
<ClInclude Include="..\..\src\libGLESv2\ProgramBinary.h"/>
<ClInclude Include="..\..\src\libGLESv2\Buffer.h"/>
<ClInclude Include="..\..\src\libGLESv2\validationES2.h"/>
<ClInclude Include="..\..\src\libGLESv2\Fence.h"/>
<ClInclude Include="..\..\src\libGLESv2\angletypes.h"/>
<ClInclude Include="..\..\src\libGLESv2\VertexArray.h"/>
<ClInclude Include="..\..\src\libGLESv2\Uniform.h"/>
<ClInclude Include="..\..\src\libGLESv2\constants.h"/>
<ClInclude Include="..\..\src\libGLESv2\main.h"/>
<ClInclude Include="..\..\src\libGLESv2\Framebuffer.h"/>
<ClInclude Include="..\..\src\libGLESv2\VertexArray.h"/>
<ClInclude Include="..\..\src\libGLESv2\angletypes.h"/>
<ClInclude Include="..\..\src\libGLESv2\formatutils.h"/>
<ClInclude Include="..\..\src\libGLESv2\RenderbufferProxySet.h"/>
<ClInclude Include="..\..\src\libGLESv2\validationES.h"/>
......@@ -288,6 +289,7 @@
<ClCompile Include="..\..\src\libGLESv2\libGLESv2.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\validationES2.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\precompiled.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\DynamicHLSL.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\queryconversions.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\HandleAllocator.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\formatutils.cpp"/>
......@@ -353,8 +355,8 @@
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\TextureStorage9.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\Fence9.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\Blit9.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\SwapChain9.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\VertexBuffer9.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\SwapChain9.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\formatutils9.cpp"/>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\Query9.cpp"/>
<ClCompile Include="..\..\src\common\event_tracer.cpp"/>
......
......@@ -81,6 +81,9 @@
<ClCompile Include="..\..\src\libGLESv2\precompiled.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libGLESv2\DynamicHLSL.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
<ClInclude Include="..\..\src\libGLESv2\queryconversions.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
......@@ -135,6 +138,9 @@
<ClCompile Include="..\..\src\libGLESv2\Context.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
<ClInclude Include="..\..\src\libGLESv2\DynamicHLSL.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
<ClCompile Include="..\..\src\libGLESv2\Fence.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
......@@ -162,15 +168,15 @@
<ClCompile Include="..\..\src\libGLESv2\Renderbuffer.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
<ClInclude Include="..\..\src\libGLESv2\angletypes.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\libGLESv2\Uniform.h">
<ClInclude Include="..\..\src\libGLESv2\VertexArray.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
<ClCompile Include="..\..\src\libGLESv2\Query.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
<ClInclude Include="..\..\src\libGLESv2\Uniform.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
<ClCompile Include="..\..\src\libGLESv2\Buffer.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
......@@ -201,6 +207,9 @@
<None Include="..\..\src\libGLESv2\libGLESv2.def">
<Filter>src\libGLESv2</Filter>
</None>
<ClInclude Include="..\..\src\libGLESv2\angletypes.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
<ClCompile Include="..\..\src\libGLESv2\validationES3.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
......@@ -216,9 +225,6 @@
<ClCompile Include="..\..\src\libGLESv2\Sampler.cpp">
<Filter>src\libGLESv2</Filter>
</ClCompile>
<ClInclude Include="..\..\src\libGLESv2\VertexArray.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\libGLESv2\formatutils.h">
<Filter>src\libGLESv2</Filter>
</ClInclude>
......@@ -678,15 +684,15 @@
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\Blit9.cpp">
<Filter>src\libGLESv2\renderer\d3d9</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\VertexBuffer9.cpp">
<Filter>src\libGLESv2\renderer\d3d9</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\SwapChain9.cpp">
<Filter>src\libGLESv2\renderer\d3d9</Filter>
</ClCompile>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d9\BufferStorage9.h">
<Filter>src\libGLESv2\renderer\d3d9</Filter>
</ClInclude>
<ClCompile Include="..\..\src\libGLESv2\renderer\d3d9\VertexBuffer9.cpp">
<Filter>src\libGLESv2\renderer\d3d9</Filter>
</ClCompile>
<ClInclude Include="..\..\src\libGLESv2\renderer\d3d9\Renderer9.h">
<Filter>src\libGLESv2\renderer\d3d9</Filter>
</ClInclude>
......
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
//
#include "precompiled.h"
#include "libGLESv2/DynamicHLSL.h"
#include "libGLESv2/Shader.h"
#include "libGLESv2/Program.h"
#include "libGLESv2/renderer/Renderer.h"
#include "common/utilities.h"
#include "libGLESv2/ProgramBinary.h"
#include "compiler/translator/HLSLLayoutEncoder.h"
namespace gl_d3d
{
std::string TypeString(GLenum type)
{
switch (type)
{
case GL_FLOAT: return "float";
case GL_FLOAT_VEC2: return "float2";
case GL_FLOAT_VEC3: return "float3";
case GL_FLOAT_VEC4: return "float4";
case GL_INT: return "int";
case GL_INT_VEC2: return "int2";
case GL_INT_VEC3: return "int3";
case GL_INT_VEC4: return "int4";
case GL_UNSIGNED_INT: return "uint";
case GL_UNSIGNED_INT_VEC2: return "uint2";
case GL_UNSIGNED_INT_VEC3: return "uint3";
case GL_UNSIGNED_INT_VEC4: return "uint4";
case GL_FLOAT_MAT2: return "float2x2";
case GL_FLOAT_MAT3: return "float3x3";
case GL_FLOAT_MAT4: return "float4x4";
case GL_FLOAT_MAT2x3: return "float2x3";
case GL_FLOAT_MAT3x2: return "float3x2";
case GL_FLOAT_MAT2x4: return "float2x4";
case GL_FLOAT_MAT4x2: return "float4x2";
case GL_FLOAT_MAT3x4: return "float3x4";
case GL_FLOAT_MAT4x3: return "float4x3";
default: UNREACHABLE(); return "invalid-gl-type";
}
}
}
namespace gl
{
static std::string Str(int i)
{
char buffer[20];
snprintf(buffer, sizeof(buffer), "%d", i);
return buffer;
}
static std::string ArrayString(int i)
{
return "[" + Str(i) + "]";
}
std::string ArrayString(unsigned int i)
{
return (i == GL_INVALID_INDEX ? "" : "[" + Str(i) + "]");
}
DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
: mRenderer(renderer)
{
}
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Returns the number of used varying registers, or -1 if unsuccesful
int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader)
{
const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
fragmentShader->resetVaryingsRegisterAssignment();
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
GLenum transposedType = TransposeMatrixType(varying->type);
// matrices within varying structs are not transposed
int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
bool success = false;
if (elements == 2 || elements == 3 || elements == 4)
{
for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
for (int x = 0; x < elements && available; x++)
{
if (packing[r + y][x])
{
available = false;
}
}
}
if (available)
{
varying->registerIndex = r;
varying->elementIndex = 0;
for (int y = 0; y < registers; y++)
{
for (int x = 0; x < elements; x++)
{
packing[r + y][x] = &*varying;
}
}
success = true;
}
}
if (!success && elements == 2)
{
for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
for (int x = 2; x < 4 && available; x++)
{
if (packing[r + y][x])
{
available = false;
}
}
}
if (available)
{
varying->registerIndex = r;
varying->elementIndex = 2;
for (int y = 0; y < registers; y++)
{
for (int x = 2; x < 4; x++)
{
packing[r + y][x] = &*varying;
}
}
success = true;
}
}
}
}
else if (elements == 1)
{
int space[4] = {0};
for (int y = 0; y < maxVaryingVectors; y++)
{
for (int x = 0; x < 4; x++)
{
space[x] += packing[y][x] ? 0 : 1;
}
}
int column = 0;
for (int x = 0; x < 4; x++)
{
if (space[x] >= registers && space[x] < space[column])
{
column = x;
}
}
if (space[column] >= registers)
{
for (int r = 0; r < maxVaryingVectors; r++)
{
if (!packing[r][column])
{
varying->registerIndex = r;
for (int y = r; y < r + registers; y++)
{
packing[y][column] = &*varying;
}
break;
}
}
varying->elementIndex = column;
success = true;
}
}
else UNREACHABLE();
if (!success)
{
infoLog.append("Could not pack varying %s", varying->name.c_str());
return -1;
}
}
// Return the number of used registers
int registers = 0;
for (int r = 0; r < maxVaryingVectors; r++)
{
if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
{
registers++;
}
}
return registers;
}
std::string DynamicHLSL::generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const
{
std::string varyingHLSL;
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
if (varying->registerAssigned())
{
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++)
{
switch (varying->interpolation)
{
case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break;
case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break;
case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break;
default: UNREACHABLE();
}
std::string n = Str(varying->registerIndex + elementIndex * variableRows + row);
// matrices within structs are not transposed, hence we do not use the special struct prefix "rm"
std::string typeString = varying->isStruct() ? "_" + varying->structName :
gl_d3d::TypeString(UniformComponentType(transposedType)) + Str(VariableColumnCount(transposedType));
varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
}
}
}
else UNREACHABLE();
}
return varyingHLSL;
}
bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader,
std::map<int, VariableLocation> *programOutputVars) const
{
if (pixelHLSL.empty() || vertexHLSL.empty())
{
return false;
}
bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
bool usesFragColor = fragmentShader->mUsesFragColor;
bool usesFragData = fragmentShader->mUsesFragData;
if (usesFragColor && usesFragData)
{
infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
return false;
}
// Write the HLSL input/output declarations
const int shaderModel = mRenderer->getMajorShaderModel();
const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
// Two cases when writing to gl_FragColor and using ESSL 1.0:
// - with a 3.0 context, the output color is copied to channel 0
// - with a 2.0 context, the output color is broadcast to all channels
const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
int shaderVersion = vertexShader->getShaderVersion();
if (registersNeeded > maxVaryingVectors)
{
infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
return false;
}
std::string varyingSemantic = (vertexShader->mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
// special varyings that use reserved registers
int reservedRegisterIndex = registers;
std::string fragCoordSemantic;
std::string pointCoordSemantic;
if (fragmentShader->mUsesFragCoord)
{
fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
}
if (fragmentShader->mUsesPointCoord)
{
// Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
// In DX11 we compute this in the GS.
if (shaderModel == 3)
{
pointCoordSemantic = "TEXCOORD0";
}
else if (shaderModel >= 4)
{
pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
}
}
vertexHLSL += "struct VS_INPUT\n"
"{\n";
int semanticIndex = 0;
const std::vector<sh::Attribute> &activeAttributes = vertexShader->mActiveAttributes;
for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
{
const sh::Attribute &attribute = activeAttributes[attributeIndex];
vertexHLSL += " " + gl_d3d::TypeString(TransposeMatrixType(attribute.type)) + " ";
vertexHLSL += decorateAttribute(attribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n";
semanticIndex += AttributeRegisterCount(attribute.type);
}
vertexHLSL += "};\n"
"\n"
"struct VS_OUTPUT\n"
"{\n";
if (shaderModel < 4)
{
vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
}
vertexHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
{
vertexHLSL += " float gl_PointSize : PSIZE;\n";
}
if (shaderModel >= 4)
{
vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
}
vertexHLSL += "};\n"
"\n"
"VS_OUTPUT main(VS_INPUT input)\n"
"{\n";
for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
{
const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
vertexHLSL += " " + decorateAttribute(attribute.name) + " = ";
if (IsMatrixType(attribute.type)) // Matrix
{
vertexHLSL += "transpose";
}
vertexHLSL += "(input." + decorateAttribute(attribute.name) + ");\n";
}
if (shaderModel >= 4)
{
vertexHLSL += "\n"
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x;\n"
" output.gl_Position.y = -gl_Position.y;\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
}
else
{
vertexHLSL += "\n"
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
" output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
{
vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
}
if (fragmentShader->mUsesFragCoord)
{
vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
}
for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++)
{
sh::Varying *varying = &vertexShader->mVaryings[vertVaryingIndex];
if (varying->registerAssigned())
{
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying->type)));
for (int row = 0; row < variableRows; row++)
{
int r = varying->registerIndex + elementIndex * variableRows + row;
vertexHLSL += " output.v" + Str(r);
bool sharedRegister = false; // Register used by multiple varyings
for (int x = 0; x < 4; x++)
{
if (packing[r][x] && packing[r][x] != packing[r][0])
{
sharedRegister = true;
break;
}
}
if(sharedRegister)
{
vertexHLSL += ".";
for (int x = 0; x < 4; x++)
{
if (packing[r][x] == &*varying)
{
switch(x)
{
case 0: vertexHLSL += "x"; break;
case 1: vertexHLSL += "y"; break;
case 2: vertexHLSL += "z"; break;
case 3: vertexHLSL += "w"; break;
}
}
}
}
vertexHLSL += " = _" + varying->name;
if (varying->isArray())
{
vertexHLSL += ArrayString(elementIndex);
}
if (variableRows > 1)
{
vertexHLSL += ArrayString(row);
}
vertexHLSL += ";\n";
}
}
}
}
vertexHLSL += "\n"
" return output;\n"
"}\n";
pixelHLSL += "struct PS_INPUT\n"
"{\n";
pixelHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
{
pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
}
// Must consume the PSIZE element if the geometry shader is not active
// We won't know if we use a GS until we draw
if (vertexShader->mUsesPointSize && shaderModel >= 4)
{
pixelHLSL += " float gl_PointSize : PSIZE;\n";
}
if (fragmentShader->mUsesFragCoord)
{
if (shaderModel >= 4)
{
pixelHLSL += " float4 dx_VPos : SV_Position;\n";
}
else if (shaderModel >= 3)
{
pixelHLSL += " float2 dx_VPos : VPOS;\n";
}
}
pixelHLSL += "};\n"
"\n"
"struct PS_OUTPUT\n"
"{\n";
if (shaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
pixelHLSL += " float4 gl_Color" + Str(renderTargetIndex) + " : " + targetSemantic + Str(renderTargetIndex) + ";\n";
}
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
}
}
else
{
defineOutputVariables(fragmentShader, programOutputVars);
const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getOutputVariables();
for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
{
const VariableLocation &outputLocation = locationIt->second;
const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
pixelHLSL += " " + gl_d3d::TypeString(outputVariable.type) +
" out_" + outputLocation.name + elementString +
" : " + targetSemantic + Str(locationIt->first) + ";\n";
}
}
pixelHLSL += "};\n"
"\n";
if (fragmentShader->mUsesFrontFacing)
{
if (shaderModel >= 4)
{
pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
"{\n";
}
else
{
pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
"{\n";
}
}
else
{
pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
"{\n";
}
if (fragmentShader->mUsesFragCoord)
{
pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
if (shaderModel >= 4)
{
pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
" gl_FragCoord.y = input.dx_VPos.y;\n";
}
else if (shaderModel >= 3)
{
pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
" gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
}
else
{
// dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
" gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
}
pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
" gl_FragCoord.w = rhw;\n";
}
if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
{
pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
}
if (fragmentShader->mUsesFrontFacing)
{
if (shaderModel <= 3)
{
pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
}
else
{
pixelHLSL += " gl_FrontFacing = isFrontFace;\n";
}
}
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
if (varying->registerAssigned())
{
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++)
{
std::string n = Str(varying->registerIndex + elementIndex * variableRows + row);
pixelHLSL += " _" + varying->name;
if (varying->isArray())
{
pixelHLSL += ArrayString(elementIndex);
}
if (variableRows > 1)
{
pixelHLSL += ArrayString(row);
}
if (varying->isStruct())
{
pixelHLSL += " = input.v" + n + ";\n"; break;
}
else
{
switch (VariableColumnCount(transposedType))
{
case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break;
case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break;
case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
case 4: pixelHLSL += " = input.v" + n + ";\n"; break;
default: UNREACHABLE();
}
}
}
}
}
else UNREACHABLE();
}
pixelHLSL += "\n"
" gl_main();\n"
"\n"
" PS_OUTPUT output;\n";
if (shaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
pixelHLSL += " output.gl_Color" + Str(renderTargetIndex) + " = gl_Color[" + Str(sourceColorIndex) + "];\n";
}
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " output.gl_Depth = gl_Depth;\n";
}
}
else
{
for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
{
const VariableLocation &outputLocation = locationIt->second;
const std::string &variableName = "out_" + outputLocation.name;
const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
const std::string &staticVariableName = variableName + ArrayString(outputLocation.element);
pixelHLSL += " output." + outVariableName + " = " + staticVariableName + ";\n";
}
}
pixelHLSL += "\n"
" return output;\n"
"}\n";
return true;
}
void DynamicHLSL::defineOutputVariables(FragmentShader *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
{
const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getOutputVariables();
for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++)
{
const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
if (outputVariable.arraySize > 0)
{
for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
{
const int location = baseLocation + elementIndex;
ASSERT(programOutputVars->count(location) == 0);
(*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
}
}
else
{
ASSERT(programOutputVars->count(baseLocation) == 0);
(*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
}
}
}
std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
{
// for now we only handle point sprite emulation
ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader);
}
std::string DynamicHLSL::generatePointSpriteHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
{
ASSERT(registers >= 0);
ASSERT(vertexShader->mUsesPointSize);
ASSERT(mRenderer->getMajorShaderModel() >= 4);
std::string geomHLSL;
std::string varyingSemantic = "TEXCOORD";
std::string fragCoordSemantic;
std::string pointCoordSemantic;
int reservedRegisterIndex = registers;
if (fragmentShader->mUsesFragCoord)
{
fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
}
if (fragmentShader->mUsesPointCoord)
{
pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
}
geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
"\n"
"struct GS_INPUT\n"
"{\n";
std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
geomHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
geomHLSL += " float gl_PointSize : PSIZE;\n"
" float4 gl_Position : SV_Position;\n"
"};\n"
"\n"
"struct GS_OUTPUT\n"
"{\n";
geomHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
if (fragmentShader->mUsesPointCoord)
{
geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
}
geomHLSL += " float gl_PointSize : PSIZE;\n"
" float4 gl_Position : SV_Position;\n"
"};\n"
"\n"
"static float2 pointSpriteCorners[] = \n"
"{\n"
" float2( 0.5f, -0.5f),\n"
" float2( 0.5f, 0.5f),\n"
" float2(-0.5f, -0.5f),\n"
" float2(-0.5f, 0.5f)\n"
"};\n"
"\n"
"static float2 pointSpriteTexcoords[] = \n"
"{\n"
" float2(1.0f, 1.0f),\n"
" float2(1.0f, 0.0f),\n"
" float2(0.0f, 1.0f),\n"
" float2(0.0f, 0.0f)\n"
"};\n"
"\n"
"static float minPointSize = " + Str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
"static float maxPointSize = " + Str(mRenderer->getMaxPointSize()) + ".0f;\n"
"\n"
"[maxvertexcount(4)]\n"
"void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
"{\n"
" GS_OUTPUT output = (GS_OUTPUT)0;\n"
" output.gl_PointSize = input[0].gl_PointSize;\n";
for (int r = 0; r < registers; r++)
{
geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n";
}
if (fragmentShader->mUsesFragCoord)
{
geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n";
}
geomHLSL += " \n"
" float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
" float4 gl_Position = input[0].gl_Position;\n"
" float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
for (int corner = 0; corner < 4; corner++)
{
geomHLSL += " \n"
" output.gl_Position = gl_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
if (fragmentShader->mUsesPointCoord)
{
geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n";
}
geomHLSL += " outStream.Append(output);\n";
}
geomHLSL += " \n"
" outStream.RestartStrip();\n"
"}\n";
return geomHLSL;
}
// This method needs to match OutputHLSL::decorate
std::string DynamicHLSL::decorateAttribute(const std::string &name)
{
if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
{
return "_" + name;
}
return name;
}
}
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DynamicHLSL.h: Interface for link and run-time HLSL generation
//
#ifndef LIBGLESV2_DYNAMIC_HLSL_H_
#define LIBGLESV2_DYNAMIC_HLSL_H_
#include "common/angleutils.h"
namespace sh
{
struct ShaderVariable;
}
namespace rx
{
class Renderer;
}
namespace gl
{
class InfoLog;
class FragmentShader;
class VertexShader;
struct VariableLocation;
class DynamicHLSL
{
public:
explicit DynamicHLSL(rx::Renderer *const renderer);
int packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader);
bool generateShaderLinkHLSL(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader,
std::map<int, VariableLocation> *programOutputVars) const;
std::string generateGeometryShaderHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
private:
DISALLOW_COPY_AND_ASSIGN(DynamicHLSL);
rx::Renderer *const mRenderer;
std::string generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const;
void defineOutputVariables(FragmentShader *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const;
std::string generatePointSpriteHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
// Prepend an underscore
static std::string decorateAttribute(const std::string &name);
};
// Utility method shared between ProgramBinary and DynamicHLSL
std::string ArrayString(unsigned int i);
}
#endif // LIBGLESV2_DYNAMIC_HLSL_H_
......@@ -23,62 +23,13 @@
#include "libGLESv2/renderer/VertexDataManager.h"
#include "libGLESv2/Context.h"
#include "libGLESv2/Buffer.h"
#include "compiler/translator/HLSLLayoutEncoder.h"
#include "libGLESv2/DynamicHLSL.h"
#undef near
#undef far
namespace gl
{
std::string str(int i)
{
char buffer[20];
snprintf(buffer, sizeof(buffer), "%d", i);
return buffer;
}
std::string arrayString(int i)
{
return "[" + str(i) + "]";
}
std::string arrayString(unsigned int i)
{
return (i == GL_INVALID_INDEX ? "" : "[" + str(i) + "]");
}
namespace gl_d3d
{
std::string TypeString(GLenum type)
{
switch (type)
{
case GL_FLOAT: return "float";
case GL_FLOAT_VEC2: return "float2";
case GL_FLOAT_VEC3: return "float3";
case GL_FLOAT_VEC4: return "float4";
case GL_INT: return "int";
case GL_INT_VEC2: return "int2";
case GL_INT_VEC3: return "int3";
case GL_INT_VEC4: return "int4";
case GL_UNSIGNED_INT: return "uint";
case GL_UNSIGNED_INT_VEC2: return "uint2";
case GL_UNSIGNED_INT_VEC3: return "uint3";
case GL_UNSIGNED_INT_VEC4: return "uint4";
case GL_FLOAT_MAT2: return "float2x2";
case GL_FLOAT_MAT3: return "float3x3";
case GL_FLOAT_MAT4: return "float4x4";
case GL_FLOAT_MAT2x3: return "float2x3";
case GL_FLOAT_MAT3x2: return "float3x2";
case GL_FLOAT_MAT2x4: return "float2x4";
case GL_FLOAT_MAT4x2: return "float4x2";
case GL_FLOAT_MAT3x4: return "float3x4";
case GL_FLOAT_MAT4x3: return "float4x3";
default: UNREACHABLE(); return "invalid-gl-type";
}
}
}
namespace
{
......@@ -99,11 +50,6 @@ unsigned int ParseAndStripArrayIndex(std::string* name)
return subscript;
}
static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard)
{
return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE);
}
}
VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
......@@ -116,6 +62,7 @@ unsigned int ProgramBinary::mCurrentSerial = 1;
ProgramBinary::ProgramBinary(rx::Renderer *renderer)
: RefCountObject(0),
mRenderer(renderer),
mDynamicHLSL(NULL),
mPixelExecutable(NULL),
mVertexExecutable(NULL),
mGeometryExecutable(NULL),
......@@ -142,6 +89,8 @@ ProgramBinary::ProgramBinary(rx::Renderer *renderer)
{
mSamplersVS[index].active = false;
}
mDynamicHLSL = new DynamicHLSL(renderer);
}
ProgramBinary::~ProgramBinary()
......@@ -164,6 +113,7 @@ ProgramBinary::~ProgramBinary()
SafeDelete(mVertexUniformStorage);
SafeDelete(mFragmentUniformStorage);
SafeDelete(mDynamicHLSL);
}
unsigned int ProgramBinary::getSerial() const
......@@ -936,234 +886,21 @@ bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuff
return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
}
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Returns the number of used varying registers, or -1 if unsuccesful
int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader)
bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader)
{
const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
fragmentShader->resetVaryingsRegisterAssignment();
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
GLenum transposedType = TransposeMatrixType(varying->type);
// matrices within varying structs are not transposed
int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
bool success = false;
if (elements == 2 || elements == 3 || elements == 4)
{
for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
for (int x = 0; x < elements && available; x++)
{
if (packing[r + y][x])
{
available = false;
}
}
}
if (available)
{
varying->registerIndex = r;
varying->elementIndex = 0;
for (int y = 0; y < registers; y++)
{
for (int x = 0; x < elements; x++)
{
packing[r + y][x] = &*varying;
}
}
success = true;
}
}
if (!success && elements == 2)
{
for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
for (int x = 2; x < 4 && available; x++)
{
if (packing[r + y][x])
{
available = false;
}
}
}
if (available)
{
varying->registerIndex = r;
varying->elementIndex = 2;
for (int y = 0; y < registers; y++)
{
for (int x = 2; x < 4; x++)
{
packing[r + y][x] = &*varying;
}
}
success = true;
}
}
}
}
else if (elements == 1)
{
int space[4] = {0};
for (int y = 0; y < maxVaryingVectors; y++)
{
for (int x = 0; x < 4; x++)
{
space[x] += packing[y][x] ? 0 : 1;
}
}
int column = 0;
for (int x = 0; x < 4; x++)
{
if (space[x] >= registers && space[x] < space[column])
{
column = x;
}
}
if (space[column] >= registers)
{
for (int r = 0; r < maxVaryingVectors; r++)
{
if (!packing[r][column])
{
varying->registerIndex = r;
for (int y = r; y < r + registers; y++)
{
packing[y][column] = &*varying;
}
break;
}
}
varying->elementIndex = column;
success = true;
}
}
else UNREACHABLE();
if (!success)
{
infoLog.append("Could not pack varying %s", varying->name.c_str());
return -1;
}
}
// Return the number of used registers
int registers = 0;
for (int r = 0; r < maxVaryingVectors; r++)
{
if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
{
registers++;
}
}
return registers;
}
void ProgramBinary::defineOutputVariables(FragmentShader *fragmentShader)
{
const std::vector<sh::Attribute> &outputVars = fragmentShader->getOutputVariables();
for (unsigned int outputVariableIndex = 0; outputVariableIndex < outputVars.size(); outputVariableIndex++)
{
const sh::Attribute &outputVariable = outputVars[outputVariableIndex];
const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
if (outputVariable.arraySize > 0)
{
for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
{
const int location = baseLocation + elementIndex;
ASSERT(mOutputVariables.count(location) == 0);
mOutputVariables[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
}
}
else
{
ASSERT(mOutputVariables.count(baseLocation) == 0);
mOutputVariables[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
}
}
}
bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader)
{
if (pixelHLSL.empty() || vertexHLSL.empty())
{
return false;
}
bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
bool usesFragColor = fragmentShader->mUsesFragColor;
bool usesFragData = fragmentShader->mUsesFragData;
if (usesFragColor && usesFragData)
{
infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
return false;
}
// Write the HLSL input/output declarations
const int shaderModel = mRenderer->getMajorShaderModel();
const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
// Two cases when writing to gl_FragColor and using ESSL 1.0:
// - with a 3.0 context, the output color is copied to channel 0
// - with a 2.0 context, the output color is broadcast to all channels
const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
if (registersNeeded > maxVaryingVectors)
{
infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
return false;
}
vertexShader->resetVaryingsRegisterAssignment();
for (unsigned int fragVaryingIndex = 0; fragVaryingIndex < fragmentShader->mVaryings.size(); fragVaryingIndex++)
std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings();
std::vector<sh::Varying> &vertexVaryings = vertexShader->getVaryings();
for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
{
sh::Varying *input = &fragmentShader->mVaryings[fragVaryingIndex];
sh::Varying *input = &fragmentVaryings[fragVaryingIndex];
bool matched = false;
for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++)
for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
{
sh::Varying *output = &vertexShader->mVaryings[vertVaryingIndex];
sh::Varying *output = &vertexVaryings[vertVaryingIndex];
if (output->name == input->name)
{
if (!linkValidateVariables(infoLog, output->name, *input, *output))
......@@ -1182,457 +919,13 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::Shad
if (!matched)
{
infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
return false;
}
}
mUsesPointSize = vertexShader->mUsesPointSize;
std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
// special varyings that use reserved registers
int reservedRegisterIndex = registers;
std::string fragCoordSemantic;
std::string pointCoordSemantic;
if (fragmentShader->mUsesFragCoord)
{
fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
}
if (fragmentShader->mUsesPointCoord)
{
// Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
// In DX11 we compute this in the GS.
if (shaderModel == 3)
{
pointCoordSemantic = "TEXCOORD0";
}
else if (shaderModel >= 4)
{
pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
}
}
vertexHLSL += "struct VS_INPUT\n"
"{\n";
int semanticIndex = 0;
const std::vector<sh::Attribute> &activeAttributes = vertexShader->mActiveAttributes;
for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
{
const sh::Attribute &attribute = activeAttributes[attributeIndex];
vertexHLSL += " " + gl_d3d::TypeString(TransposeMatrixType(attribute.type)) + " ";
vertexHLSL += decorateAttribute(attribute.name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
semanticIndex += AttributeRegisterCount(attribute.type);
}
vertexHLSL += "};\n"
"\n"
"struct VS_OUTPUT\n"
"{\n";
if (shaderModel < 4)
{
vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
}
vertexHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
{
vertexHLSL += " float gl_PointSize : PSIZE;\n";
}
if (shaderModel >= 4)
{
vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
}
vertexHLSL += "};\n"
"\n"
"VS_OUTPUT main(VS_INPUT input)\n"
"{\n";
for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
{
const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
vertexHLSL += " " + decorateAttribute(attribute.name) + " = ";
if (IsMatrixType(attribute.type)) // Matrix
{
vertexHLSL += "transpose";
}
vertexHLSL += "(input." + decorateAttribute(attribute.name) + ");\n";
}
if (shaderModel >= 4)
{
vertexHLSL += "\n"
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x;\n"
" output.gl_Position.y = -gl_Position.y;\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
}
else
{
vertexHLSL += "\n"
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
" output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
{
vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
}
if (fragmentShader->mUsesFragCoord)
{
vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
}
for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++)
{
sh::Varying *varying = &vertexShader->mVaryings[vertVaryingIndex];
if (varying->registerAssigned())
{
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying->type)));
for (int row = 0; row < variableRows; row++)
{
int r = varying->registerIndex + elementIndex * variableRows + row;
vertexHLSL += " output.v" + str(r);
bool sharedRegister = false; // Register used by multiple varyings
for (int x = 0; x < 4; x++)
{
if (packing[r][x] && packing[r][x] != packing[r][0])
{
sharedRegister = true;
break;
}
}
if(sharedRegister)
{
vertexHLSL += ".";
for (int x = 0; x < 4; x++)
{
if (packing[r][x] == &*varying)
{
switch(x)
{
case 0: vertexHLSL += "x"; break;
case 1: vertexHLSL += "y"; break;
case 2: vertexHLSL += "z"; break;
case 3: vertexHLSL += "w"; break;
}
}
}
}
vertexHLSL += " = _" + varying->name;
if (varying->isArray())
{
vertexHLSL += arrayString(elementIndex);
}
if (variableRows > 1)
{
vertexHLSL += arrayString(row);
}
vertexHLSL += ";\n";
}
}
}
}
vertexHLSL += "\n"
" return output;\n"
"}\n";
pixelHLSL += "struct PS_INPUT\n"
"{\n";
pixelHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
{
pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
}
// Must consume the PSIZE element if the geometry shader is not active
// We won't know if we use a GS until we draw
if (vertexShader->mUsesPointSize && shaderModel >= 4)
{
pixelHLSL += " float gl_PointSize : PSIZE;\n";
}
if (fragmentShader->mUsesFragCoord)
{
if (shaderModel >= 4)
{
pixelHLSL += " float4 dx_VPos : SV_Position;\n";
}
else if (shaderModel >= 3)
{
pixelHLSL += " float2 dx_VPos : VPOS;\n";
}
}
pixelHLSL += "};\n"
"\n"
"struct PS_OUTPUT\n"
"{\n";
if (mShaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
}
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
}
}
else
{
defineOutputVariables(fragmentShader);
const std::vector<sh::Attribute> &outputVars = fragmentShader->getOutputVariables();
for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
{
const VariableLocation &outputLocation = locationIt->second;
const sh::ShaderVariable &outputVariable = outputVars[outputLocation.index];
const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : str(outputLocation.element));
pixelHLSL += " " + gl_d3d::TypeString(outputVariable.type) +
" out_" + outputLocation.name + elementString +
" : " + targetSemantic + str(locationIt->first) + ";\n";
}
}
pixelHLSL += "};\n"
"\n";
if (fragmentShader->mUsesFrontFacing)
{
if (shaderModel >= 4)
{
pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
"{\n";
}
else
{
pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
"{\n";
}
}
else
{
pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
"{\n";
}
if (fragmentShader->mUsesFragCoord)
{
pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
if (shaderModel >= 4)
{
pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
" gl_FragCoord.y = input.dx_VPos.y;\n";
}
else if (shaderModel >= 3)
{
pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
" gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
}
else
{
// dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
" gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
}
pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
" gl_FragCoord.w = rhw;\n";
}
if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
{
pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
}
if (fragmentShader->mUsesFrontFacing)
{
if (shaderModel <= 3)
{
pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
}
else
{
pixelHLSL += " gl_FrontFacing = isFrontFace;\n";
}
}
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
if (varying->registerAssigned())
{
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++)
{
std::string n = str(varying->registerIndex + elementIndex * variableRows + row);
pixelHLSL += " _" + varying->name;
if (varying->isArray())
{
pixelHLSL += arrayString(elementIndex);
}
if (variableRows > 1)
{
pixelHLSL += arrayString(row);
}
if (varying->isStruct())
{
pixelHLSL += " = input.v" + n + ";\n"; break;
}
else
{
switch (VariableColumnCount(transposedType))
{
case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break;
case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break;
case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
case 4: pixelHLSL += " = input.v" + n + ";\n"; break;
default: UNREACHABLE();
}
}
}
}
}
else UNREACHABLE();
}
pixelHLSL += "\n"
" gl_main();\n"
"\n"
" PS_OUTPUT output;\n";
if (mShaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
}
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " output.gl_Depth = gl_Depth;\n";
}
}
else
{
for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
{
const VariableLocation &outputLocation = locationIt->second;
const std::string &variableName = "out_" + outputLocation.name;
const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : str(outputLocation.element));
const std::string &staticVariableName = variableName + arrayString(outputLocation.element);
pixelHLSL += " output." + outVariableName + " = " + staticVariableName + ";\n";
}
}
pixelHLSL += "\n"
" return output;\n"
"}\n";
return true;
}
std::string ProgramBinary::generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const
{
std::string varyingHLSL;
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
if (varying->registerAssigned())
{
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++)
{
switch (varying->interpolation)
{
case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break;
case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break;
case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break;
default: UNREACHABLE();
}
std::string n = str(varying->registerIndex + elementIndex * variableRows + row);
// matrices within structs are not transposed, hence we do not use the special struct prefix "rm"
std::string typeString = varying->isStruct() ? "_" + varying->structName :
gl_d3d::TypeString(UniformComponentType(transposedType)) + str(VariableColumnCount(transposedType));
varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
}
}
}
else UNREACHABLE();
}
return varyingHLSL;
}
bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
{
BinaryInputStream stream(binary, length);
......@@ -2045,14 +1338,20 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
// Map the varyings to the register file
const sh::ShaderVariable *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL};
int registers = packVaryings(infoLog, packing, fragmentShader);
int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader);
if (registers < 0)
{
return false;
}
if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
if (!linkVaryings(infoLog, fragmentShader, vertexShader))
{
return false;
}
mUsesPointSize = vertexShader->usesPointSize();
if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader, &mOutputVariables))
{
return false;
}
......@@ -2070,7 +1369,7 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
}
// special case for gl_DepthRange, the only built-in uniform (also a struct)
if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
if (vertexShader->usesDepthRange() || fragmentShader->usesDepthRange())
{
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
......@@ -2084,12 +1383,12 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
if (success)
{
mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting));
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting));
mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, vertexShader->getD3DWorkarounds());
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, vertexShader->getD3DWorkarounds());
if (usesGeometryShader())
{
std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE);
}
......@@ -2114,7 +1413,7 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
{
unsigned int usedLocations = 0;
const std::vector<sh::Attribute> &activeAttributes = vertexShader->mActiveAttributes;
const std::vector<sh::Attribute> &activeAttributes = vertexShader->activeAttributes();
// Link attributes that have a binding location
for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
......@@ -2414,12 +1713,11 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++)
{
const sh::Uniform &field = constant.fields[fieldIndex];
const std::string &uniformName = constant.name + arrayString(elementIndex) + "." + field.name;
const std::string &uniformName = constant.name + ArrayString(elementIndex) + "." + field.name;
sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize,
elementRegisterIndex, field.elementIndex);
fieldUniform.fields = field.fields;
if (!defineUniform(shader, fieldUniform, infoLog))
{
return false;
......@@ -2659,7 +1957,7 @@ void ProgramBinary::defineUniformBlockMembers(const std::vector<sh::InterfaceBlo
{
for (unsigned int arrayElement = 0; arrayElement < field.arraySize; arrayElement++)
{
const std::string uniformElementName = fieldName + arrayString(arrayElement);
const std::string uniformElementName = fieldName + ArrayString(arrayElement);
defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, blockInfoItr, blockUniformIndexes);
}
}
......@@ -2760,146 +2058,6 @@ bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *u
return true;
}
std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
{
// for now we only handle point sprite emulation
ASSERT(usesPointSpriteEmulation());
return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader);
}
std::string ProgramBinary::generatePointSpriteHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
{
ASSERT(registers >= 0);
ASSERT(vertexShader->mUsesPointSize);
ASSERT(mRenderer->getMajorShaderModel() >= 4);
std::string geomHLSL;
std::string varyingSemantic = "TEXCOORD";
std::string fragCoordSemantic;
std::string pointCoordSemantic;
int reservedRegisterIndex = registers;
if (fragmentShader->mUsesFragCoord)
{
fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
}
if (fragmentShader->mUsesPointCoord)
{
pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
}
geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
"\n"
"struct GS_INPUT\n"
"{\n";
std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
geomHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
geomHLSL += " float gl_PointSize : PSIZE;\n"
" float4 gl_Position : SV_Position;\n"
"};\n"
"\n"
"struct GS_OUTPUT\n"
"{\n";
geomHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
}
if (fragmentShader->mUsesPointCoord)
{
geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
}
geomHLSL += " float gl_PointSize : PSIZE;\n"
" float4 gl_Position : SV_Position;\n"
"};\n"
"\n"
"static float2 pointSpriteCorners[] = \n"
"{\n"
" float2( 0.5f, -0.5f),\n"
" float2( 0.5f, 0.5f),\n"
" float2(-0.5f, -0.5f),\n"
" float2(-0.5f, 0.5f)\n"
"};\n"
"\n"
"static float2 pointSpriteTexcoords[] = \n"
"{\n"
" float2(1.0f, 1.0f),\n"
" float2(1.0f, 0.0f),\n"
" float2(0.0f, 1.0f),\n"
" float2(0.0f, 0.0f)\n"
"};\n"
"\n"
"static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
"static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n"
"\n"
"[maxvertexcount(4)]\n"
"void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
"{\n"
" GS_OUTPUT output = (GS_OUTPUT)0;\n"
" output.gl_PointSize = input[0].gl_PointSize;\n";
for (int r = 0; r < registers; r++)
{
geomHLSL += " output.v" + str(r) + " = input[0].v" + str(r) + ";\n";
}
if (fragmentShader->mUsesFragCoord)
{
geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n";
}
geomHLSL += " \n"
" float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
" float4 gl_Position = input[0].gl_Position;\n"
" float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
for (int corner = 0; corner < 4; corner++)
{
geomHLSL += " \n"
" output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
if (fragmentShader->mUsesPointCoord)
{
geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n";
}
geomHLSL += " outStream.Append(output);\n";
}
geomHLSL += " \n"
" outStream.RestartStrip();\n"
"}\n";
return geomHLSL;
}
// This method needs to match OutputHLSL::decorate
std::string ProgramBinary::decorateAttribute(const std::string &name)
{
if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
{
return "_" + name;
}
return name;
}
bool ProgramBinary::isValidated() const
{
return mValidated;
......@@ -3061,7 +2219,7 @@ void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei
if (uniformBlock.isArrayElement())
{
string += arrayString(uniformBlock.elementIndex);
string += ArrayString(uniformBlock.elementIndex);
}
strncpy(uniformBlockName, string.c_str(), bufSize);
......
......@@ -32,6 +32,7 @@ class ShaderExecutable;
class Renderer;
struct TranslatedAttribute;
class UniformStorage;
class DynamicHLSL;
}
namespace gl
......@@ -144,8 +145,6 @@ class ProgramBinary : public RefCountObject
void initAttributesByLayout();
void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
static std::string decorateAttribute(const std::string &name); // Prepend an underscore
const UniformArray &getUniforms() const { return mUniforms; }
const rx::UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; }
const rx::UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
......@@ -153,12 +152,7 @@ class ProgramBinary : public RefCountObject
private:
DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
int packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader);
bool linkVaryings(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader);
std::string generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const;
bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader);
bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
typedef sh::BlockMemberInfoArray::const_iterator BlockInfoItr;
......@@ -180,9 +174,6 @@ class ProgramBinary : public RefCountObject
void defineOutputVariables(FragmentShader *fragmentShader);
void initializeUniformStorage();
std::string generateGeometryShaderHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
std::string generatePointSpriteHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
template <typename T>
bool setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
......@@ -195,6 +186,7 @@ class ProgramBinary : public RefCountObject
static TextureType getTextureType(GLenum samplerType, InfoLog &infoLog);
rx::Renderer *const mRenderer;
DynamicHLSL *mDynamicHLSL;
rx::ShaderExecutable *mPixelExecutable;
rx::ShaderExecutable *mVertexExecutable;
......@@ -222,10 +214,8 @@ class ProgramBinary : public RefCountObject
UniformArray mUniforms;
UniformBlockArray mUniformBlocks;
typedef std::vector<VariableLocation> UniformIndex;
UniformIndex mUniformIndex;
typedef std::map<int, VariableLocation> ShaderVariableIndex;
ShaderVariableIndex mOutputVariables;
std::vector<VariableLocation> mUniformIndex;
std::map<int, VariableLocation> mOutputVariables;
rx::UniformStorage *mVertexUniformStorage;
rx::UniformStorage *mFragmentUniformStorage;
......@@ -236,6 +226,7 @@ class ProgramBinary : public RefCountObject
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
};
}
#endif // LIBGLESV2_PROGRAM_BINARY_H_
......@@ -125,6 +125,11 @@ const sh::ActiveInterfaceBlocks &Shader::getInterfaceBlocks() const
return mActiveInterfaceBlocks;
}
std::vector<sh::Varying> &Shader::getVaryings()
{
return mVaryings;
}
bool Shader::isCompiled() const
{
return !mHlsl.empty();
......@@ -368,6 +373,16 @@ void Shader::compileToHLSL(void *compiler)
}
}
rx::D3DWorkaroundType Shader::getD3DWorkarounds() const
{
if (mUsesDiscardRewriting)
{
return rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER;
}
return rx::ANGLE_D3D_WORKAROUND_NONE;
}
// [OpenGL ES SL 3.00.4] Section 11 p. 120
// Vertex Outs/Fragment Ins packing priorities
static const GLenum varyingPriorityList[] =
......
......@@ -21,6 +21,7 @@
#include "compiler/translator/ShaderVariable.h"
#include "common/angleutils.h"
#include "libGLESv2/angletypes.h"
namespace rx
{
......@@ -33,7 +34,7 @@ class ResourceManager;
class Shader
{
friend class ProgramBinary;
friend class DynamicHLSL;
public:
Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle);
......@@ -53,6 +54,7 @@ class Shader
void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
const std::vector<sh::Uniform> &getUniforms() const;
const sh::ActiveInterfaceBlocks &getInterfaceBlocks() const;
std::vector<sh::Varying> &getVaryings();
virtual void compile() = 0;
virtual void uncompile();
......@@ -65,12 +67,16 @@ class Shader
bool isFlaggedForDeletion() const;
void flagForDeletion();
int getShaderVersion() const;
void resetVaryingsRegisterAssignment();
static void releaseCompiler();
bool usesDepthRange() const { return mUsesDepthRange; }
bool usesPointSize() const { return mUsesPointSize; }
rx::D3DWorkaroundType getD3DWorkarounds() const;
protected:
void parseVaryings(void *compiler);
void resetVaryingsRegisterAssignment();
void compileToHLSL(void *compiler);
......@@ -117,7 +123,7 @@ class Shader
class VertexShader : public Shader
{
friend class ProgramBinary;
friend class DynamicHLSL;
public:
VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle);
......@@ -129,6 +135,8 @@ class VertexShader : public Shader
virtual void uncompile();
int getSemanticIndex(const std::string &attributeName);
const std::vector<sh::Attribute> &activeAttributes() const { return mActiveAttributes; }
private:
DISALLOW_COPY_AND_ASSIGN(VertexShader);
......
......@@ -253,6 +253,12 @@ enum VertexConversionType
VERTEX_CONVERT_BOTH = 3
};
enum D3DWorkaroundType
{
ANGLE_D3D_WORKAROUND_NONE,
ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER
};
}
#endif // LIBGLESV2_ANGLETYPES_H_
......@@ -97,12 +97,6 @@ enum ShaderType
SHADER_GEOMETRY
};
enum D3DWorkaroundType
{
ANGLE_D3D_WORKAROUND_NONE,
ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER
};
class Renderer
{
public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment