Commit 9fc3682c by Jamie Madill

D3D: Rework varying packing code.

In D3D we pack varyings by making a register map, and using the recommended GLSL ES algorithm to reserve register space. We use this map to assign row and column slots to each varying and then produce a semantic index value. The existing scheme had a number of bugs, and was failing several angle_end2end_tests. The new design cleans up the code somewhat and uses a different counting scheme for the semantic indexes: just sort the varyings in packing order and use a simple incrementing semantic index per varying. In SM4+, the HLSL compiler sorts and packs the varyings correctly itself, and in SM3, handle the cases we don't support by returning an error instead of a D3D compiler link error. Also refactor how we store varying information for TF Feedback/ StreamOut. Only store the necessary D3D information, instead of extra information like the name and type. This fixes several tests in GLSLTest/*. This also will allow us to fix interpolation qualifier packing and the structure packing in HLSL, which seems to work differently than the rest of the varying types. BUG=angleproject:1202 TEST=bots,dEQP-GLES3.functional.transform_feedback.* Change-Id: Ie5bfbb4f71d8bf97f39115fc46d2e61b131df639 Reviewed-on: https://chromium-review.googlesource.com/311241Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e39a3f0a
...@@ -48,6 +48,8 @@ const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableLis ...@@ -48,6 +48,8 @@ const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableLis
return *variableList; return *variableList;
} }
} // anonymous namespace
// true if varying x has a higher priority in packing than y // true if varying x has a higher priority in packing than y
bool CompareVarying(const sh::Varying &x, const sh::Varying &y) bool CompareVarying(const sh::Varying &x, const sh::Varying &y)
{ {
...@@ -70,8 +72,6 @@ bool CompareVarying(const sh::Varying &x, const sh::Varying &y) ...@@ -70,8 +72,6 @@ bool CompareVarying(const sh::Varying &x, const sh::Varying &y)
return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type); return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
} }
} // anonymous namespace
Shader::Data::Data(GLenum shaderType) : mShaderType(shaderType), mShaderVersion(100) Shader::Data::Data(GLenum shaderType) : mShaderType(shaderType), mShaderVersion(100)
{ {
} }
......
...@@ -137,6 +137,7 @@ class Shader : angle::NonCopyable ...@@ -137,6 +137,7 @@ class Shader : angle::NonCopyable
ResourceManager *mResourceManager; ResourceManager *mResourceManager;
}; };
bool CompareVarying(const sh::Varying &x, const sh::Varying &y);
} }
#endif // LIBANGLE_SHADER_H_ #endif // LIBANGLE_SHADER_H_
...@@ -118,24 +118,23 @@ std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize) ...@@ -118,24 +118,23 @@ std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD"); return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
} }
// DynamicHLSL implementation
DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
{ {
} }
void DynamicHLSL::generateVaryingHLSL(const gl::Caps &caps, void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking,
const std::vector<PackedVarying> &varyings,
bool programUsesPointSize,
std::stringstream &hlslStream) const std::stringstream &hlslStream) const
{ {
std::string varyingSemantic = std::string varyingSemantic =
GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize); GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize());
for (const PackedVaryingRegister &registerInfo : PackedVaryingIterator(varyings)) for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
{ {
const PackedVarying &packedVarying = varyings[registerInfo.varyingIndex]; const sh::Varying &varying = *registerInfo.packedVarying->varying;
const sh::Varying &varying = *packedVarying.varying; GLenum transposedType = gl::TransposeMatrixType(varying.type);
GLenum transposedType = gl::TransposeMatrixType(varying.type); unsigned int semanticIndex = registerInfo.semanticIndex;
unsigned int registerIndex = registerInfo.registerIndex(caps, varyings);
// TODO: Add checks to ensure D3D interpolation modifiers don't result in too many // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
// registers being used. // registers being used.
...@@ -171,7 +170,7 @@ void DynamicHLSL::generateVaryingHLSL(const gl::Caps &caps, ...@@ -171,7 +170,7 @@ void DynamicHLSL::generateVaryingHLSL(const gl::Caps &caps,
hlslStream << HLSLComponentTypeString(componentType, columnCount); hlslStream << HLSLComponentTypeString(componentType, columnCount);
} }
hlslStream << " v" << registerIndex << " : " << varyingSemantic << registerIndex << ";\n"; hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
} }
} }
...@@ -360,97 +359,48 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature( ...@@ -360,97 +359,48 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
return pixelHLSL; return pixelHLSL;
} }
void DynamicHLSL::generateVaryingLinkHLSL(const gl::Caps &caps, void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType,
bool programUsesPointSize, const VaryingPacking &varyingPacking,
const SemanticInfo &info,
const std::vector<PackedVarying> &packedVaryings,
std::stringstream &linkStream) const std::stringstream &linkStream) const
{ {
ASSERT(info.dxPosition.enabled); const auto &builtins = varyingPacking.builtins(shaderType);
ASSERT(builtins.dxPosition.enabled);
linkStream << "{\n" linkStream << "{\n"
<< " float4 dx_Position : " << info.dxPosition.str() << ";\n"; << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
if (info.glPosition.enabled) if (builtins.glPosition.enabled)
{ {
linkStream << " float4 gl_Position : " << info.glPosition.str() << ";\n"; linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n";
} }
if (info.glFragCoord.enabled) if (builtins.glFragCoord.enabled)
{ {
linkStream << " float4 gl_FragCoord : " << info.glFragCoord.str() << ";\n"; linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
} }
if (info.glPointCoord.enabled) if (builtins.glPointCoord.enabled)
{ {
linkStream << " float2 gl_PointCoord : " << info.glPointCoord.str() << ";\n"; linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
} }
if (info.glPointSize.enabled) if (builtins.glPointSize.enabled)
{ {
linkStream << " float gl_PointSize : " << info.glPointSize.str() << ";\n"; linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
} }
// Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the
// same register. // same register.
generateVaryingHLSL(caps, packedVaryings, programUsesPointSize, linkStream); generateVaryingHLSL(varyingPacking, linkStream);
linkStream << "};\n"; linkStream << "};\n";
} }
void DynamicHLSL::storeBuiltinVaryings(const SemanticInfo &info,
std::vector<D3DVarying> *d3dVaryingsOut) const
{
if (info.glPosition.enabled)
{
d3dVaryingsOut->push_back(D3DVarying("gl_Position", GL_FLOAT_VEC4, 1,
info.glPosition.semantic, info.glPosition.index, 1));
}
if (info.glFragCoord.enabled)
{
d3dVaryingsOut->push_back(D3DVarying("gl_FragCoord", GL_FLOAT_VEC4, 1,
info.glFragCoord.semantic, info.glFragCoord.index, 1));
}
if (info.glPointSize.enabled)
{
d3dVaryingsOut->push_back(D3DVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1));
}
}
void DynamicHLSL::storeUserVaryings(const std::vector<PackedVarying> &packedVaryings,
bool programUsesPointSize,
std::vector<D3DVarying> *d3dVaryingsOut) const
{
const std::string &varyingSemantic =
GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize);
for (const PackedVarying &packedVarying : packedVaryings)
{
if (packedVarying.registerAssigned())
{
const sh::Varying &varying = *packedVarying.varying;
ASSERT(!varying.isBuiltIn());
GLenum transposedType = TransposeMatrixType(varying.type);
int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
d3dVaryingsOut->push_back(D3DVarying(varying.name, varying.type, varying.elementCount(),
varyingSemantic, packedVarying.registerIndex,
variableRows * varying.elementCount()));
}
}
}
bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData, const gl::Program::Data &programData,
const ProgramD3DMetadata &programMetadata, const ProgramD3DMetadata &programMetadata,
InfoLog &infoLog, const VaryingPacking &varyingPacking,
unsigned int registerCount,
std::string *pixelHLSL, std::string *pixelHLSL,
std::string *vertexHLSL, std::string *vertexHLSL) const
const std::vector<PackedVarying> &packedVaryings,
std::vector<D3DVarying> *d3dVaryingsOut) const
{ {
ASSERT(pixelHLSL->empty() && vertexHLSL->empty()); ASSERT(pixelHLSL->empty() && vertexHLSL->empty());
...@@ -460,9 +410,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -460,9 +410,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL); const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL);
const int shaderModel = mRenderer->getMajorShaderModel(); const int shaderModel = mRenderer->getMajorShaderModel();
bool usesFragCoord = programMetadata.usesFragCoord();
bool usesPointCoord = fragmentShader->usesPointCoord();
bool usesPointSize = vertexShader->usesPointSize();
bool useInstancedPointSpriteEmulation = bool useInstancedPointSpriteEmulation =
programMetadata.usesPointSize() && programMetadata.usesPointSize() &&
mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
...@@ -470,29 +417,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -470,29 +417,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
// Validation done in the compiler // Validation done in the compiler
ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData()); ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
// Write the HLSL input/output declarations
const unsigned int registersNeeded =
registerCount + (usesFragCoord ? 1u : 0u) + (usesPointCoord ? 1u : 0u);
if (static_cast<GLuint>(registersNeeded) > data.caps->maxVaryingVectors)
{
infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
return false;
}
// Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader
// VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
// GeometryShader PointSprite emulation does not require this additional entry because the
// GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the
// PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs
// gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need
// gl_PointSize in VS_OUTPUT.
const SemanticInfo &vertexSemantics =
GetSemanticInfo(SHADER_VERTEX, programMetadata, registerCount);
storeUserVaryings(packedVaryings, usesPointSize, d3dVaryingsOut);
storeBuiltinVaryings(vertexSemantics, d3dVaryingsOut);
std::stringstream vertexStream; std::stringstream vertexStream;
vertexStream << vertexShaderGL->getTranslatedSource(); vertexStream << vertexShaderGL->getTranslatedSource();
...@@ -507,10 +431,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -507,10 +431,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
} }
// Add stub string to be replaced when shader is dynamically defined by its layout // Add stub string to be replaced when shader is dynamically defined by its layout
vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n" vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n";
<< "struct VS_OUTPUT\n";
generateVaryingLinkHLSL(*data.caps, usesPointSize, vertexSemantics, packedVaryings, // Write the HLSL input/output declarations
vertexStream); vertexStream << "struct VS_OUTPUT\n";
generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream);
vertexStream << "\n" vertexStream << "\n"
<< "VS_OUTPUT main(VS_INPUT input)\n" << "VS_OUTPUT main(VS_INPUT input)\n"
<< "{\n" << "{\n"
...@@ -527,7 +452,9 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -527,7 +452,9 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
<< "\n" << "\n"
<< " VS_OUTPUT output;\n"; << " VS_OUTPUT output;\n";
if (vertexSemantics.glPosition.enabled) const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX);
if (vertexBuiltins.glPosition.enabled)
{ {
vertexStream << " output.gl_Position = gl_Position;\n"; vertexStream << " output.gl_Position = gl_Position;\n";
} }
...@@ -551,35 +478,33 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -551,35 +478,33 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
} }
// We don't need to output gl_PointSize if we use are emulating point sprites via instancing. // We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
if (usesPointSize && shaderModel >= 3 && !useInstancedPointSpriteEmulation) if (vertexBuiltins.glPointSize.enabled)
{ {
vertexStream << " output.gl_PointSize = gl_PointSize;\n"; vertexStream << " output.gl_PointSize = gl_PointSize;\n";
} }
if (usesFragCoord) if (vertexBuiltins.glFragCoord.enabled)
{ {
vertexStream << " output.gl_FragCoord = gl_Position;\n"; vertexStream << " output.gl_FragCoord = gl_Position;\n";
} }
for (const PackedVaryingRegister &registerInfo : PackedVaryingIterator(packedVaryings)) for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
{ {
const PackedVarying &packedVarying = packedVaryings[registerInfo.varyingIndex]; const sh::Varying &varying = *registerInfo.packedVarying->varying;
const sh::Varying &varying = *packedVarying.varying;
GLenum transposedType = TransposeMatrixType(varying.type); GLenum transposedType = TransposeMatrixType(varying.type);
unsigned int variableRows = unsigned int variableRows =
static_cast<unsigned int>(varying.isStruct() ? 1 : VariableRowCount(transposedType)); static_cast<unsigned int>(varying.isStruct() ? 1 : VariableRowCount(transposedType));
int r = registerInfo.registerIndex(*data.caps, packedVaryings); vertexStream << " output.v" << registerInfo.semanticIndex << " = _" + varying.name;
vertexStream << " output.v" << r << " = _" + varying.name;
if (varying.isArray()) if (varying.isArray())
{ {
vertexStream << ArrayString(registerInfo.elementIndex); vertexStream << ArrayString(registerInfo.varyingArrayIndex);
} }
if (variableRows > 1) if (variableRows > 1)
{ {
vertexStream << ArrayString(registerInfo.rowIndex); vertexStream << ArrayString(registerInfo.varyingRowIndex);
} }
vertexStream << ";\n"; vertexStream << ";\n";
...@@ -619,12 +544,8 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -619,12 +544,8 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
std::stringstream pixelStream; std::stringstream pixelStream;
pixelStream << fragmentShaderGL->getTranslatedSource(); pixelStream << fragmentShaderGL->getTranslatedSource();
const SemanticInfo &pixelSemantics =
GetSemanticInfo(SHADER_PIXEL, programMetadata, registerCount);
pixelStream << "struct PS_INPUT\n"; pixelStream << "struct PS_INPUT\n";
generateVaryingLinkHLSL(*data.caps, usesPointSize, pixelSemantics, packedVaryings, pixelStream); generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream);
pixelStream << "\n"; pixelStream << "\n";
pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n"; pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n";
...@@ -648,7 +569,9 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -648,7 +569,9 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
<< "{\n"; << "{\n";
} }
if (usesFragCoord) const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL);
if (pixelBuiltins.glFragCoord.enabled)
{ {
pixelStream << " float rhw = 1.0 / input.gl_FragCoord.w;\n"; pixelStream << " float rhw = 1.0 / input.gl_FragCoord.w;\n";
...@@ -680,7 +603,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -680,7 +603,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
<< " gl_FragCoord.w = rhw;\n"; << " gl_FragCoord.w = rhw;\n";
} }
if (usesPointCoord && shaderModel >= 3) if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3)
{ {
pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n" pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n"
<< " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
...@@ -698,32 +621,30 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -698,32 +621,30 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
} }
} }
for (const PackedVaryingRegister &registerInfo : PackedVaryingIterator(packedVaryings)) for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
{ {
const PackedVarying &packedVarying = packedVaryings[registerInfo.varyingIndex]; const sh::Varying &varying = *registerInfo.packedVarying->varying;
const sh::Varying &varying = *packedVarying.varying;
// Don't reference VS-only transform feedback varyings in the PS. // Don't reference VS-only transform feedback varyings in the PS.
if (packedVarying.vertexOnly) if (registerInfo.packedVarying->vertexOnly)
continue; continue;
ASSERT(!varying.isBuiltIn()); ASSERT(!varying.isBuiltIn());
GLenum transposedType = TransposeMatrixType(varying.type); GLenum transposedType = TransposeMatrixType(varying.type);
int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
unsigned int registerIndex = registerInfo.registerIndex(*data.caps, packedVaryings);
pixelStream << " _" << varying.name; pixelStream << " _" << varying.name;
if (varying.isArray()) if (varying.isArray())
{ {
pixelStream << ArrayString(registerInfo.elementIndex); pixelStream << ArrayString(registerInfo.varyingArrayIndex);
} }
if (variableRows > 1) if (variableRows > 1)
{ {
pixelStream << ArrayString(registerInfo.rowIndex); pixelStream << ArrayString(registerInfo.varyingRowIndex);
} }
pixelStream << " = input.v" << registerIndex; pixelStream << " = input.v" << registerInfo.semanticIndex;
if (!varying.isStruct()) if (!varying.isStruct())
{ {
...@@ -765,64 +686,43 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, ...@@ -765,64 +686,43 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
return true; return true;
} }
std::string DynamicHLSL::generateGeometryShaderPreamble( std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const
const gl::Data &data,
const gl::Program::Data &programData,
const ProgramD3DMetadata &programMetadata,
unsigned int registerCount,
const std::vector<PackedVarying> &packedVaryings) const
{ {
int majorShaderModel = mRenderer->getMajorShaderModel(); ASSERT(mRenderer->getMajorShaderModel() >= 4);
ASSERT(registerCount >= 0 && registerCount <= data.caps->maxVaryingVectors);
ASSERT(majorShaderModel >= 4);
// Must be called during link, not from a binary load.
const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(programData.getAttachedVertexShader());
const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(programData.getAttachedFragmentShader());
ASSERT(vertexShader && fragmentShader);
bool usesFragCoord = fragmentShader->usesFragCoord();
bool usesPointSize = vertexShader->usesPointSize();
const SemanticInfo &inSemantics =
GetSemanticInfo(SHADER_VERTEX, programMetadata, registerCount);
const SemanticInfo &outSemantics =
GetSemanticInfo(SHADER_GEOMETRY, programMetadata, registerCount);
std::stringstream preambleStream; std::stringstream preambleStream;
const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
preambleStream << "struct GS_INPUT\n"; preambleStream << "struct GS_INPUT\n";
generateVaryingLinkHLSL(*data.caps, usesPointSize, inSemantics, packedVaryings, preambleStream); generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream);
preambleStream << "\n" preambleStream << "\n"
<< "struct GS_OUTPUT\n"; << "struct GS_OUTPUT\n";
generateVaryingLinkHLSL(*data.caps, usesPointSize, outSemantics, packedVaryings, generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream);
preambleStream);
preambleStream preambleStream
<< "\n" << "\n"
<< "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n" << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
<< "{\n" << "{\n"
<< " output.gl_Position = input.gl_Position;\n"; << " output.gl_Position = input.gl_Position;\n";
if (usesPointSize) if (builtins.glPointSize.enabled)
{ {
preambleStream << " output.gl_PointSize = input.gl_PointSize;\n"; preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
} }
for (const PackedVaryingRegister &varyingRegister : PackedVaryingIterator(packedVaryings)) for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList())
{ {
const sh::Varying &varying = *packedVaryings[varyingRegister.varyingIndex].varying; const sh::Varying &varying = *varyingRegister.packedVarying->varying;
unsigned int registerIndex = varyingRegister.registerIndex(*data.caps, packedVaryings);
preambleStream << " output.v" << registerIndex << " = "; preambleStream << " output.v" << varyingRegister.semanticIndex << " = ";
if (varying.interpolation == sh::INTERPOLATION_FLAT) if (varying.interpolation == sh::INTERPOLATION_FLAT)
{ {
preambleStream << "flat"; preambleStream << "flat";
} }
preambleStream << "input.v" << registerIndex << "; \n"; preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n";
} }
if (usesFragCoord) if (builtins.glFragCoord.enabled)
{ {
preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n"; preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n";
} }
......
...@@ -37,8 +37,8 @@ namespace rx ...@@ -37,8 +37,8 @@ namespace rx
{ {
struct PackedVarying; struct PackedVarying;
class ProgramD3DMetadata; class ProgramD3DMetadata;
struct SemanticInfo;
class ShaderD3D; class ShaderD3D;
class VaryingPacking;
struct PixelShaderOutputVariable struct PixelShaderOutputVariable
{ {
...@@ -65,19 +65,11 @@ class DynamicHLSL : angle::NonCopyable ...@@ -65,19 +65,11 @@ class DynamicHLSL : angle::NonCopyable
bool generateShaderLinkHLSL(const gl::Data &data, bool generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData, const gl::Program::Data &programData,
const ProgramD3DMetadata &programMetadata, const ProgramD3DMetadata &programMetadata,
gl::InfoLog &infoLog, const VaryingPacking &varyingPacking,
unsigned int registerCount,
std::string *pixelHLSL, std::string *pixelHLSL,
std::string *vertexHLSL, std::string *vertexHLSL) const;
const std::vector<PackedVarying> &packedVaryings,
std::vector<D3DVarying> *d3dVaryingsOut) const;
std::string generateGeometryShaderPreamble( std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const;
const gl::Data &data,
const gl::Program::Data &programData,
const ProgramD3DMetadata &programMetadata,
unsigned int registers,
const std::vector<PackedVarying> &packedVaryings) const;
std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::Data &data, const gl::Data &data,
...@@ -92,20 +84,11 @@ class DynamicHLSL : angle::NonCopyable ...@@ -92,20 +84,11 @@ class DynamicHLSL : angle::NonCopyable
private: private:
RendererD3D *const mRenderer; RendererD3D *const mRenderer;
void generateVaryingLinkHLSL(const gl::Caps &caps, void generateVaryingLinkHLSL(ShaderType shaderType,
bool programUsesPointSize, const VaryingPacking &varyingPacking,
const SemanticInfo &info,
const std::vector<PackedVarying> &packedVaryings,
std::stringstream &linkStream) const; std::stringstream &linkStream) const;
void generateVaryingHLSL(const gl::Caps &caps, void generateVaryingHLSL(const VaryingPacking &varyingPacking,
const std::vector<PackedVarying> &varyings,
bool programUsesPointSize,
std::stringstream &hlslStream) const; std::stringstream &hlslStream) const;
void storeUserVaryings(const std::vector<PackedVarying> &packedVaryings,
bool programUsesPointSize,
std::vector<D3DVarying> *d3dVaryingsOut) const;
void storeBuiltinVaryings(const SemanticInfo &info,
std::vector<D3DVarying> *d3dVaryingsOut) const;
// Prepend an underscore // Prepend an underscore
static std::string decorateVariable(const std::string &name); static std::string decorateVariable(const std::string &name);
......
...@@ -101,6 +101,12 @@ struct AttributeSorter ...@@ -101,6 +101,12 @@ struct AttributeSorter
const ProgramD3D::SemanticIndexArray *originalIndices; const ProgramD3D::SemanticIndexArray *originalIndices;
}; };
// true if varying x has a higher priority in packing than y
bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
{
return gl::CompareVarying(*x.varying, *y.varying);
}
std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader, std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
const gl::Shader &fragmentShader, const gl::Shader &fragmentShader,
const std::vector<std::string> &tfVaryings) const std::vector<std::string> &tfVaryings)
...@@ -142,6 +148,8 @@ std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader, ...@@ -142,6 +148,8 @@ std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
} }
} }
std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying);
return packedVaryings; return packedVaryings;
} }
...@@ -344,22 +352,18 @@ bool D3DUniform::isReferencedByFragmentShader() const ...@@ -344,22 +352,18 @@ bool D3DUniform::isReferencedByFragmentShader() const
// D3DVarying Implementation // D3DVarying Implementation
D3DVarying::D3DVarying() D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
{ {
} }
D3DVarying::D3DVarying(const std::string &name, D3DVarying::D3DVarying(const std::string &semanticNameIn,
GLenum type, unsigned int semanticIndexIn,
GLsizei size, unsigned int componentCountIn,
const std::string &semanticName, unsigned int outputSlotIn)
unsigned int semanticIndex, : semanticName(semanticNameIn),
unsigned int semanticIndexCount) semanticIndex(semanticIndexIn),
: name(name), componentCount(componentCountIn),
type(type), outputSlot(outputSlotIn)
size(size),
semanticName(semanticName),
semanticIndex(semanticIndex),
semanticIndexCount(semanticIndexCount)
{ {
} }
...@@ -781,19 +785,16 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) ...@@ -781,19 +785,16 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
mD3DUniformBlocks.push_back(uniformBlock); mD3DUniformBlocks.push_back(uniformBlock);
} }
const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>(); const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
mTransformFeedbackD3DVaryings.resize(transformFeedbackVaryingCount); mStreamOutVaryings.resize(streamOutVaryingCount);
for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
varyingIndex++)
{ {
D3DVarying *varying = &mTransformFeedbackD3DVaryings[varyingIndex]; D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
stream->readString(&varying->name);
stream->readInt(&varying->type);
stream->readInt(&varying->size);
stream->readString(&varying->semanticName); stream->readString(&varying->semanticName);
stream->readInt(&varying->semanticIndex); stream->readInt(&varying->semanticIndex);
stream->readInt(&varying->semanticIndexCount); stream->readInt(&varying->componentCount);
stream->readInt(&varying->outputSlot);
} }
stream->readString(&mVertexHLSL); stream->readString(&mVertexHLSL);
...@@ -839,7 +840,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) ...@@ -839,7 +840,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
ShaderExecutableD3D *shaderExecutable = nullptr; ShaderExecutableD3D *shaderExecutable = nullptr;
gl::Error error = mRenderer->loadExecutable( gl::Error error = mRenderer->loadExecutable(
vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackD3DVaryings, vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
if (error.isError()) if (error.isError())
{ {
...@@ -878,7 +879,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) ...@@ -878,7 +879,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
ShaderExecutableD3D *shaderExecutable = nullptr; ShaderExecutableD3D *shaderExecutable = nullptr;
gl::Error error = mRenderer->loadExecutable( gl::Error error = mRenderer->loadExecutable(
pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackD3DVaryings, pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
if (error.isError()) if (error.isError())
{ {
...@@ -911,8 +912,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) ...@@ -911,8 +912,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS); bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
gl::Error error = mRenderer->loadExecutable( gl::Error error = mRenderer->loadExecutable(
geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, mStreamOutVaryings,
mTransformFeedbackD3DVaryings, splitAttribs, &mGeometryExecutables[geometryExeIndex]); splitAttribs, &mGeometryExecutables[geometryExeIndex]);
if (error.isError()) if (error.isError())
{ {
return LinkResult(false, error); return LinkResult(false, error);
...@@ -985,17 +986,13 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) ...@@ -985,17 +986,13 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(uniformBlock.vsRegisterIndex); stream->writeInt(uniformBlock.vsRegisterIndex);
} }
stream->writeInt(mTransformFeedbackD3DVaryings.size()); stream->writeInt(mStreamOutVaryings.size());
for (size_t i = 0; i < mTransformFeedbackD3DVaryings.size(); i++) for (const auto &varying : mStreamOutVaryings)
{ {
const D3DVarying &varying = mTransformFeedbackD3DVaryings[i];
stream->writeString(varying.name);
stream->writeInt(varying.type);
stream->writeInt(varying.size);
stream->writeString(varying.semanticName); stream->writeString(varying.semanticName);
stream->writeInt(varying.semanticIndex); stream->writeInt(varying.semanticIndex);
stream->writeInt(varying.semanticIndexCount); stream->writeInt(varying.componentCount);
stream->writeInt(varying.outputSlot);
} }
stream->writeString(mVertexHLSL); stream->writeString(mVertexHLSL);
...@@ -1130,7 +1127,7 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum ...@@ -1130,7 +1127,7 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
gl::Error error = mRenderer->compileToExecutable( gl::Error error = mRenderer->compileToExecutable(
*currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackD3DVaryings, *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds, (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
&pixelExecutable); &pixelExecutable);
if (error.isError()) if (error.isError())
...@@ -1179,7 +1176,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i ...@@ -1179,7 +1176,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
gl::Error error = mRenderer->compileToExecutable( gl::Error error = mRenderer->compileToExecutable(
*currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackD3DVaryings, *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds, (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
&vertexExecutable); &vertexExecutable);
if (error.isError()) if (error.isError())
...@@ -1238,7 +1235,7 @@ gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data ...@@ -1238,7 +1235,7 @@ gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
gl::Error error = mRenderer->compileToExecutable( gl::Error error = mRenderer->compileToExecutable(
*currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackD3DVaryings, *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(), (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
&mGeometryExecutables[geometryShaderType]); &mGeometryExecutables[geometryShaderType]);
...@@ -1353,9 +1350,9 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog) ...@@ -1353,9 +1350,9 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames()); MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
// Map the varyings to the register file // Map the varyings to the register file
unsigned int registerCount = 0; VaryingPacking varyingPacking(data.caps->maxVaryingVectors);
if (!PackVaryings(*data.caps, infoLog, &packedVaryings, if (!varyingPacking.packVaryings(infoLog, packedVaryings,
mData.getTransformFeedbackVaryingNames(), &registerCount)) mData.getTransformFeedbackVaryingNames()))
{ {
return LinkResult(false, gl::Error(GL_NO_ERROR)); return LinkResult(false, gl::Error(GL_NO_ERROR));
} }
...@@ -1364,10 +1361,27 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog) ...@@ -1364,10 +1361,27 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
usesInstancedPointSpriteEmulation(), vertexShaderD3D, usesInstancedPointSpriteEmulation(), vertexShaderD3D,
fragmentShaderD3D); fragmentShaderD3D);
std::vector<D3DVarying> d3dVaryings; varyingPacking.enableBuiltins(SHADER_VERTEX, metadata);
if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, infoLog, registerCount, varyingPacking.enableBuiltins(SHADER_PIXEL, metadata);
&mPixelHLSL, &mVertexHLSL, packedVaryings,
&d3dVaryings)) if (static_cast<GLuint>(varyingPacking.getRegisterCount()) > data.caps->maxVaryingVectors)
{
infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
// TODO(jmadill): Implement more sophisticated component packing in D3D9.
// We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
// intelligently, but D3D9 assumes one semantic per register.
if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
varyingPacking.getMaxSemanticIndex() > data.caps->maxVaryingVectors)
{
infoLog << "Cannot pack these varyings on D3D9.";
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, varyingPacking, &mPixelHLSL,
&mVertexHLSL))
{ {
return LinkResult(false, gl::Error(GL_NO_ERROR)); return LinkResult(false, gl::Error(GL_NO_ERROR));
} }
...@@ -1388,15 +1402,15 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog) ...@@ -1388,15 +1402,15 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
if (mRenderer->getMajorShaderModel() >= 4) if (mRenderer->getMajorShaderModel() >= 4)
{ {
mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble( varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata);
data, mData, metadata, registerCount, packedVaryings); mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking);
} }
initSemanticIndex(); initSemanticIndex();
defineUniformsAndAssignRegisters(); defineUniformsAndAssignRegisters();
gatherTransformFeedbackVaryings(d3dVaryings); gatherTransformFeedbackVaryings(varyingPacking);
LinkResult result = compileProgramExecutables(data, infoLog); LinkResult result = compileProgramExecutables(data, infoLog);
if (result.error.isError() || !result.linkSuccess) if (result.error.isError() || !result.linkSuccess)
...@@ -2113,7 +2127,7 @@ void ProgramD3D::reset() ...@@ -2113,7 +2127,7 @@ void ProgramD3D::reset()
std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1); std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1); std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
mTransformFeedbackD3DVaryings.clear(); mStreamOutVaryings.clear();
mGeometryShaderPreamble.clear(); mGeometryShaderPreamble.clear();
} }
...@@ -2195,18 +2209,60 @@ void ProgramD3D::updateCachedInputLayout(const gl::State &state) ...@@ -2195,18 +2209,60 @@ void ProgramD3D::updateCachedInputLayout(const gl::State &state)
} }
} }
void ProgramD3D::gatherTransformFeedbackVaryings(const std::vector<D3DVarying> &d3dVaryings) void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking)
{ {
const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
const std::string &varyingSemantic =
GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
// Gather the linked varyings that are used for transform feedback, they should all exist. // Gather the linked varyings that are used for transform feedback, they should all exist.
mTransformFeedbackD3DVaryings.clear(); mStreamOutVaryings.clear();
for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
const auto &tfVaryingNames = mData.getTransformFeedbackVaryingNames();
for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
++outputSlot)
{ {
for (const D3DVarying &d3dVarying : d3dVaryings) const auto &tfVaryingName = tfVaryingNames[outputSlot];
if (tfVaryingName == "gl_Position")
{ {
if (tfVaryingName == d3dVarying.name) if (builtins.glPosition.enabled)
{ {
mTransformFeedbackD3DVaryings.push_back(d3dVarying); mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic,
break; builtins.glPosition.index, 4, outputSlot));
}
}
else if (tfVaryingName == "gl_FragCoord")
{
if (builtins.glFragCoord.enabled)
{
mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
builtins.glFragCoord.index, 4, outputSlot));
}
}
else if (tfVaryingName == "gl_PointSize")
{
if (builtins.glPointSize.enabled)
{
mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
}
}
else
{
for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
{
const sh::Varying &varying = *registerInfo.packedVarying->varying;
GLenum transposedType = gl::TransposeMatrixType(varying.type);
int componentCount = gl::VariableColumnCount(transposedType);
ASSERT(!varying.isBuiltIn());
// There can be more than one register assigned to a particular varying, and each
// register needs its own stream out entry.
if (tfVaryingName == varying.name)
{
mStreamOutVaryings.push_back(D3DVarying(
varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
}
} }
} }
} }
......
...@@ -80,26 +80,21 @@ struct D3DUniformBlock ...@@ -80,26 +80,21 @@ struct D3DUniformBlock
unsigned int psRegisterIndex; unsigned int psRegisterIndex;
}; };
struct D3DVarying struct D3DVarying final
{ {
D3DVarying(); D3DVarying();
D3DVarying(const std::string &name, D3DVarying(const std::string &semanticNameIn,
GLenum type, unsigned int semanticIndexIn,
GLsizei size, unsigned int componentCountIn,
const std::string &semanticName, unsigned int outputSlotIn);
unsigned int semanticIndex,
unsigned int semanticIndexCount);
// Original GL name
std::string name;
GLenum type; D3DVarying(const D3DVarying &) = default;
GLsizei size; D3DVarying &operator=(const D3DVarying &) = default;
// DirectX semantic information
std::string semanticName; std::string semanticName;
unsigned int semanticIndex; unsigned int semanticIndex;
unsigned int semanticIndexCount; unsigned int componentCount;
unsigned int outputSlot;
}; };
class ProgramD3DMetadata : angle::NonCopyable class ProgramD3DMetadata : angle::NonCopyable
...@@ -336,7 +331,7 @@ class ProgramD3D : public ProgramImpl ...@@ -336,7 +331,7 @@ class ProgramD3D : public ProgramImpl
LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog); LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog);
void gatherTransformFeedbackVaryings(const std::vector<D3DVarying> &varyings); void gatherTransformFeedbackVaryings(const VaryingPacking &varyings);
D3DUniform *getD3DUniformByName(const std::string &name); D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location); D3DUniform *getD3DUniformFromLocation(GLint location);
...@@ -394,7 +389,7 @@ class ProgramD3D : public ProgramImpl ...@@ -394,7 +389,7 @@ class ProgramD3D : public ProgramImpl
VertexExecutable::Signature mCachedVertexSignature; VertexExecutable::Signature mCachedVertexSignature;
gl::InputLayout mCachedInputLayout; gl::InputLayout mCachedInputLayout;
std::vector<D3DVarying> mTransformFeedbackD3DVaryings; std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms; std::vector<D3DUniform *> mD3DUniforms;
std::vector<D3DUniformBlock> mD3DUniformBlocks; std::vector<D3DUniformBlock> mD3DUniformBlocks;
......
...@@ -56,7 +56,8 @@ enum ShaderType ...@@ -56,7 +56,8 @@ enum ShaderType
{ {
SHADER_VERTEX, SHADER_VERTEX,
SHADER_PIXEL, SHADER_PIXEL,
SHADER_GEOMETRY SHADER_GEOMETRY,
SHADER_TYPE_MAX
}; };
struct DeviceIdentifier struct DeviceIdentifier
...@@ -206,13 +207,13 @@ class RendererD3D : public Renderer, public BufferFactoryD3D ...@@ -206,13 +207,13 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual gl::Error loadExecutable(const void *function, virtual gl::Error loadExecutable(const void *function,
size_t length, size_t length,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) = 0; ShaderExecutableD3D **outExecutable) = 0;
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, virtual gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL, const std::string &shaderHLSL,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) = 0; ShaderExecutableD3D **outExectuable) = 0;
......
...@@ -18,269 +18,238 @@ ...@@ -18,269 +18,238 @@
namespace rx namespace rx
{ {
SemanticInfo::BuiltinInfo::BuiltinInfo() : enabled(false), index(0), systemValue(false) // Implementation of VaryingPacking::BuiltinVarying
VaryingPacking::BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false)
{ {
} }
std::string SemanticInfo::BuiltinInfo::str() const std::string VaryingPacking::BuiltinVarying::str() const
{ {
return (systemValue ? semantic : (semantic + Str(index))); return (systemValue ? semantic : (semantic + Str(index)));
} }
void SemanticInfo::BuiltinInfo::enableSystem(const std::string &systemValueSemantic) void VaryingPacking::BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
{ {
enabled = true; enabled = true;
semantic = systemValueSemantic; semantic = systemValueSemantic;
systemValue = true; systemValue = true;
} }
void SemanticInfo::BuiltinInfo::enable(const std::string &semanticVal, unsigned int indexVal) void VaryingPacking::BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
{ {
enabled = true; enabled = true;
semantic = semanticVal; semantic = semanticVal;
index = indexVal; index = indexVal;
} }
bool PackVarying(PackedVarying *packedVarying, const int maxVaryingVectors, VaryingPacking &packing) // Implementation of VaryingPacking
VaryingPacking::VaryingPacking(GLuint maxVaryingVectors)
: mRegisterMap(maxVaryingVectors), mBuiltinInfo(SHADER_TYPE_MAX)
{ {
// Make sure we use transposed matrix types to count registers correctly. }
int registers = 0;
int elements = 0; // Packs varyings into generic varying registers, using the algorithm from
// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
// Returns false if unsuccessful.
bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
{
unsigned int varyingRows = 0;
unsigned int varyingColumns = 0;
const sh::Varying &varying = *packedVarying->varying; const sh::Varying &varying = *packedVarying.varying;
if (varying.isStruct()) if (varying.isStruct())
{ {
registers = HLSLVariableRegisterCount(varying, true) * varying.elementCount(); varyingRows = HLSLVariableRegisterCount(varying, true);
elements = 4; varyingColumns = 4;
} }
else else
{ {
// "Non - square matrices of type matCxR consume the same space as a square matrix of type
// matN where N is the greater of C and R.Variables of type mat2 occupies 2 complete rows."
// Here we are a bit more conservative and allow packing non-square matrices more tightly.
// Make sure we use transposed matrix types to count registers correctly.
GLenum transposedType = gl::TransposeMatrixType(varying.type); GLenum transposedType = gl::TransposeMatrixType(varying.type);
registers = gl::VariableRowCount(transposedType) * varying.elementCount(); varyingRows = gl::VariableRowCount(transposedType);
elements = gl::VariableColumnCount(transposedType); varyingColumns = gl::VariableColumnCount(transposedType);
} }
if (elements >= 2 && elements <= 4) // "Arrays of size N are assumed to take N times the size of the base type"
{ varyingRows *= varying.elementCount();
for (int r = 0; r <= maxVaryingVectors - registers; r++)
{
bool available = true;
for (int y = 0; y < registers && available; y++) unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
{
for (int x = 0; x < elements && available; x++)
{
if (packing[r + y][x])
{
available = false;
}
}
}
if (available) // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row.
// Variables are then allocated to successive rows, aligning them to the 1st column."
if (varyingColumns >= 2 && varyingColumns <= 4)
{
for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
{
if (isFree(row, 0, varyingRows, varyingColumns))
{ {
packedVarying->registerIndex = r; insert(row, 0, packedVarying);
packedVarying->columnIndex = 0;
for (int y = 0; y < registers; y++)
{
for (int x = 0; x < elements; x++)
{
packing[r + y][x] = packedVarying;
}
}
return true; return true;
} }
} }
if (elements == 2) // "For 2 component variables, when there are no spare rows, the strategy is switched to
// using the highest numbered row and the lowest numbered column where the variable will
// fit."
if (varyingColumns == 2)
{ {
for (int r = maxVaryingVectors - registers; r >= 0; r--) for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
{ {
bool available = true; if (isFree(r, 2, varyingRows, 2))
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)
{ {
packedVarying->registerIndex = r; insert(r, 2, packedVarying);
packedVarying->columnIndex = 2;
for (int y = 0; y < registers; y++)
{
for (int x = 2; x < 4; x++)
{
packing[r + y][x] = packedVarying;
}
}
return true; return true;
} }
} }
} }
return false;
} }
else if (elements == 1)
{
int space[4] = {0};
for (int y = 0; y < maxVaryingVectors; y++) // "1 component variables have their own packing rule. They are packed in order of size, largest
// first. Each variable is placed in the column that leaves the least amount of space in the
// column and aligned to the lowest available rows within that column."
ASSERT(varyingColumns == 1);
unsigned int contiguousSpace[4] = {0};
unsigned int bestContiguousSpace[4] = {0};
unsigned int totalSpace[4] = {0};
for (unsigned int row = 0; row < maxVaryingVectors; ++row)
{
for (unsigned int column = 0; column < 4; ++column)
{ {
for (int x = 0; x < 4; x++) if (mRegisterMap[row][column])
{ {
space[x] += packing[y][x] ? 0 : 1; contiguousSpace[column] = 0;
} }
} else
{
contiguousSpace[column]++;
totalSpace[column]++;
int column = 0; if (contiguousSpace[column] > bestContiguousSpace[column])
{
bestContiguousSpace[column] = contiguousSpace[column];
}
}
}
}
for (int x = 0; x < 4; x++) unsigned int bestColumn = 0;
for (unsigned int column = 1; column < 4; ++column)
{
if (bestContiguousSpace[column] >= varyingRows &&
(bestContiguousSpace[bestColumn] < varyingRows ||
totalSpace[column] < totalSpace[bestColumn]))
{ {
if (space[x] >= registers && (space[column] < registers || space[x] < space[column])) bestColumn = column;
{
column = x;
}
} }
}
if (space[column] >= registers) if (bestContiguousSpace[bestColumn] >= varyingRows)
{
for (unsigned int row = 0; row < maxVaryingVectors; row++)
{ {
for (int r = 0; r < maxVaryingVectors; r++) if (isFree(row, bestColumn, varyingRows, 1))
{ {
if (!packing[r][column]) for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
{ {
packedVarying->registerIndex = r; // If varyingRows > 1, it must be an array.
packedVarying->columnIndex = column; PackedVaryingRegister registerInfo;
registerInfo.packedVarying = &packedVarying;
for (int y = r; y < r + registers; y++) registerInfo.registerRow = row + arrayIndex;
{ registerInfo.registerColumn = bestColumn;
packing[y][column] = packedVarying; registerInfo.varyingArrayIndex = arrayIndex;
} registerInfo.varyingRowIndex = 0;
mRegisterList.push_back(registerInfo);
break; mRegisterMap[row + arrayIndex][bestColumn] = true;
} }
break;
} }
return true;
} }
return true;
} }
else
UNREACHABLE();
return false; return false;
} }
unsigned int PackedVaryingRegister::registerIndex( bool VaryingPacking::isFree(unsigned int registerRow,
const gl::Caps &caps, unsigned int registerColumn,
const std::vector<PackedVarying> &packedVaryings) const unsigned int varyingRows,
unsigned int varyingColumns) const
{ {
const PackedVarying &packedVarying = packedVaryings[varyingIndex]; for (unsigned int row = 0; row < varyingRows; ++row)
const sh::Varying &varying = *packedVarying.varying;
GLenum transposedType = gl::TransposeMatrixType(varying.type);
unsigned int variableRows =
static_cast<unsigned int>(varying.isStruct() ? 1 : gl::VariableRowCount(transposedType));
return (elementIndex * variableRows + (packedVarying.columnIndex * caps.maxVaryingVectors) +
(packedVarying.registerIndex + rowIndex));
}
PackedVaryingIterator::PackedVaryingIterator(const std::vector<PackedVarying> &packedVaryings)
: mPackedVaryings(packedVaryings), mEnd(*this)
{
mEnd.setEnd();
}
PackedVaryingIterator::Iterator PackedVaryingIterator::begin() const
{
return Iterator(*this);
}
const PackedVaryingIterator::Iterator &PackedVaryingIterator::end() const
{
return mEnd;
}
PackedVaryingIterator::Iterator::Iterator(const PackedVaryingIterator &parent) : mParent(parent)
{
while (mRegister.varyingIndex < mParent.mPackedVaryings.size() &&
!mParent.mPackedVaryings[mRegister.varyingIndex].registerAssigned())
{ {
++mRegister.varyingIndex; ASSERT(registerRow + row < mRegisterMap.size());
for (unsigned int column = 0; column < varyingColumns; ++column)
{
ASSERT(registerColumn + column < 4);
if (mRegisterMap[registerRow + row][registerColumn + column])
{
return false;
}
}
} }
return true;
} }
PackedVaryingIterator::Iterator &PackedVaryingIterator::Iterator::operator++() void VaryingPacking::insert(unsigned int registerRow,
unsigned int registerColumn,
const PackedVarying &packedVarying)
{ {
const sh::Varying *varying = mParent.mPackedVaryings[mRegister.varyingIndex].varying; unsigned int varyingRows = 0;
GLenum transposedType = gl::TransposeMatrixType(varying->type); unsigned int varyingColumns = 0;
unsigned int variableRows =
static_cast<unsigned int>(varying->isStruct() ? 1 : gl::VariableRowCount(transposedType));
// Innermost iteration: row count const sh::Varying &varying = *packedVarying.varying;
if (mRegister.rowIndex + 1 < variableRows) if (varying.isStruct())
{ {
++mRegister.rowIndex; varyingRows = HLSLVariableRegisterCount(varying, true);
return *this; varyingColumns = 4;
} }
else
mRegister.rowIndex = 0;
// Middle iteration: element count
if (mRegister.elementIndex + 1 < varying->elementCount())
{ {
++mRegister.elementIndex; GLenum transposedType = gl::TransposeMatrixType(varying.type);
return *this; varyingRows = gl::VariableRowCount(transposedType);
varyingColumns = gl::VariableColumnCount(transposedType);
} }
mRegister.elementIndex = 0; PackedVaryingRegister registerInfo;
registerInfo.packedVarying = &packedVarying;
registerInfo.registerColumn = registerColumn;
// Outer iteration: the varying itself. Once we pass the last varying, this Iterator will for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement)
// equal the end Iterator.
do
{ {
++mRegister.varyingIndex; for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
} while (mRegister.varyingIndex < mParent.mPackedVaryings.size() && {
!mParent.mPackedVaryings[mRegister.varyingIndex].registerAssigned()); registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
return *this; registerInfo.varyingRowIndex = varyingRow;
} registerInfo.varyingArrayIndex = arrayElement;
mRegisterList.push_back(registerInfo);
bool PackedVaryingIterator::Iterator::operator==(const Iterator &other) const
{
return mRegister.elementIndex == other.mRegister.elementIndex &&
mRegister.rowIndex == other.mRegister.rowIndex &&
mRegister.varyingIndex == other.mRegister.varyingIndex;
}
bool PackedVaryingIterator::Iterator::operator!=(const Iterator &other) const for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
{ {
return !(*this == other); mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
}
}
}
} }
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading // See comment on packVarying.
// Language 1.00 rev. 17] appendix A section 7 page 111 bool VaryingPacking::packVaryings(gl::InfoLog &infoLog,
// Returns the number of used varying registers, or -1 if unsuccesful const std::vector<PackedVarying> &packedVaryings,
bool PackVaryings(const gl::Caps &caps, const std::vector<std::string> &transformFeedbackVaryings)
gl::InfoLog &infoLog,
std::vector<PackedVarying> *packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings,
unsigned int *registerCountOut)
{ {
VaryingPacking packing = {};
*registerCountOut = 0;
std::set<std::string> uniqueVaryingNames; std::set<std::string> uniqueVaryingNames;
for (PackedVarying &packedVarying : *packedVaryings) // "Variables are packed into the registers one at a time so that they each occupy a contiguous
// subrectangle. No splitting of variables is permitted."
for (const PackedVarying &packedVarying : packedVaryings)
{ {
const sh::Varying &varying = *packedVarying.varying; const sh::Varying &varying = *packedVarying.varying;
...@@ -292,7 +261,7 @@ bool PackVaryings(const gl::Caps &caps, ...@@ -292,7 +261,7 @@ bool PackVaryings(const gl::Caps &caps,
ASSERT(uniqueVaryingNames.count(varying.name) == 0); ASSERT(uniqueVaryingNames.count(varying.name) == 0);
if (PackVarying(&packedVarying, caps.maxVaryingVectors, packing)) if (packVarying(packedVarying))
{ {
uniqueVaryingNames.insert(varying.name); uniqueVaryingNames.insert(varying.name);
} }
...@@ -311,7 +280,7 @@ bool PackVaryings(const gl::Caps &caps, ...@@ -311,7 +280,7 @@ bool PackVaryings(const gl::Caps &caps,
continue; continue;
} }
for (PackedVarying &packedVarying : *packedVaryings) for (const PackedVarying &packedVarying : packedVaryings)
{ {
const sh::Varying &varying = *packedVarying.varying; const sh::Varying &varying = *packedVarying.varying;
...@@ -321,7 +290,7 @@ bool PackVaryings(const gl::Caps &caps, ...@@ -321,7 +290,7 @@ bool PackVaryings(const gl::Caps &caps,
bool found = false; bool found = false;
if (transformFeedbackVaryingName == varying.name) if (transformFeedbackVaryingName == varying.name)
{ {
if (!PackVarying(&packedVarying, caps.maxVaryingVectors, packing)) if (!packVarying(packedVarying))
{ {
infoLog << "Could not pack varying " << varying.name; infoLog << "Could not pack varying " << varying.name;
return false; return false;
...@@ -337,67 +306,84 @@ bool PackVaryings(const gl::Caps &caps, ...@@ -337,67 +306,84 @@ bool PackVaryings(const gl::Caps &caps,
return false; return false;
} }
} }
// Add duplicate transform feedback varyings for 'flat' shaded attributes. This is
// necessary because we write out modified vertex data to correct for the provoking
// vertex in D3D11. This extra transform feedback varying is the unmodified stream.
if (varying.interpolation == sh::INTERPOLATION_FLAT)
{
sh::Varying duplicateVarying(varying);
duplicateVarying.name = "StreamOut_" + duplicateVarying.name;
}
} }
} }
// Return the number of used registers // Sort the packed register list
for (GLuint r = 0; r < caps.maxVaryingVectors; r++) std::sort(mRegisterList.begin(), mRegisterList.end());
// Assign semantic indices
for (unsigned int semanticIndex = 0;
semanticIndex < static_cast<unsigned int>(mRegisterList.size()); ++semanticIndex)
{ {
if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) mRegisterList[semanticIndex].semanticIndex = semanticIndex;
}
return true;
}
unsigned int VaryingPacking::getRegisterCount() const
{
unsigned int count = 0;
for (const Register &reg : mRegisterMap)
{
if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3])
{ {
(*registerCountOut)++; ++count;
} }
} }
return true; if (mBuiltinInfo[SHADER_PIXEL].glFragCoord.enabled)
{
++count;
}
if (mBuiltinInfo[SHADER_PIXEL].glPointCoord.enabled)
{
++count;
}
return count;
} }
SemanticInfo GetSemanticInfo(ShaderType shaderType, void VaryingPacking::enableBuiltins(ShaderType shaderType,
const ProgramD3DMetadata &programMetadata, const ProgramD3DMetadata &programMetadata)
unsigned int startRegisters)
{ {
int majorShaderModel = programMetadata.getRendererMajorShaderModel(); int majorShaderModel = programMetadata.getRendererMajorShaderModel();
bool position = programMetadata.usesTransformFeedbackGLPosition(); bool position = programMetadata.usesTransformFeedbackGLPosition();
bool fragCoord = programMetadata.usesFragCoord(); bool fragCoord = programMetadata.usesFragCoord();
bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader() bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader()
: programMetadata.usesPointCoord(); : programMetadata.usesPointCoord();
bool pointSize = programMetadata.usesSystemValuePointSize(); bool pointSize = programMetadata.usesSystemValuePointSize();
bool hlsl4 = (majorShaderModel >= 4); bool hlsl4 = (majorShaderModel >= 4);
const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize);
unsigned int reservedSemanticIndex = getMaxSemanticIndex();
const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize); BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
unsigned int reservedRegisterIndex = startRegisters;
SemanticInfo info;
if (hlsl4) if (hlsl4)
{ {
info.dxPosition.enableSystem("SV_Position"); builtins->dxPosition.enableSystem("SV_Position");
} }
else if (shaderType == SHADER_PIXEL) else if (shaderType == SHADER_PIXEL)
{ {
info.dxPosition.enableSystem("VPOS"); builtins->dxPosition.enableSystem("VPOS");
} }
else else
{ {
info.dxPosition.enableSystem("POSITION"); builtins->dxPosition.enableSystem("POSITION");
} }
if (position) if (position)
{ {
info.glPosition.enable(userSemantic, reservedRegisterIndex++); builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
} }
if (fragCoord) if (fragCoord)
{ {
info.glFragCoord.enable(userSemantic, reservedRegisterIndex++); builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
} }
if (pointCoord) if (pointCoord)
...@@ -406,21 +392,19 @@ SemanticInfo GetSemanticInfo(ShaderType shaderType, ...@@ -406,21 +392,19 @@ SemanticInfo GetSemanticInfo(ShaderType shaderType,
// In D3D11 we manually compute gl_PointCoord in the GS. // In D3D11 we manually compute gl_PointCoord in the GS.
if (hlsl4) if (hlsl4)
{ {
info.glPointCoord.enable(userSemantic, reservedRegisterIndex++); builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
} }
else else
{ {
info.glPointCoord.enable("TEXCOORD", 0); builtins->glPointCoord.enable("TEXCOORD", 0);
} }
} }
// Special case: do not include PSIZE semantic in HLSL 3 pixel shaders // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
if (pointSize && (shaderType != SHADER_PIXEL || hlsl4)) if (pointSize && (shaderType != SHADER_PIXEL || hlsl4))
{ {
info.glPointSize.enableSystem("PSIZE"); builtins->glPointSize.enableSystem("PSIZE");
} }
return info;
} }
} // namespace rx } // namespace rx
...@@ -19,88 +19,92 @@ class ProgramD3DMetadata; ...@@ -19,88 +19,92 @@ class ProgramD3DMetadata;
struct PackedVarying struct PackedVarying
{ {
PackedVarying(const sh::Varying &varyingIn) PackedVarying(const sh::Varying &varyingIn) : varying(&varyingIn), vertexOnly(false) {}
: varying(&varyingIn), registerIndex(GL_INVALID_INDEX), columnIndex(0), vertexOnly(false)
{
}
bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
void resetRegisterAssignment() { registerIndex = GL_INVALID_INDEX; }
const sh::Varying *varying; const sh::Varying *varying;
// Assigned during link
unsigned int registerIndex;
// Assigned during link, Defaults to 0
unsigned int columnIndex;
// Transform feedback varyings can be only referenced in the VS. // Transform feedback varyings can be only referenced in the VS.
bool vertexOnly; bool vertexOnly;
}; };
struct PackedVaryingRegister final struct PackedVaryingRegister final
{ {
PackedVaryingRegister() : varyingIndex(0), elementIndex(0), rowIndex(0) {} PackedVaryingRegister()
: packedVarying(nullptr),
varyingArrayIndex(0),
varyingRowIndex(0),
registerRow(0),
registerColumn(0)
{
}
PackedVaryingRegister(const PackedVaryingRegister &) = default; PackedVaryingRegister(const PackedVaryingRegister &) = default;
PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default; PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
unsigned int registerIndex(const gl::Caps &caps, bool operator<(const PackedVaryingRegister &other) const
const std::vector<PackedVarying> &packedVaryings) const; {
return sortOrder() < other.sortOrder();
}
unsigned int sortOrder() const
{
// TODO(jmadill): Handle interpolation types
return registerRow * 4 + registerColumn;
}
// Index to the array of varyings.
const PackedVarying *packedVarying;
// The array element of the packed varying.
unsigned int varyingArrayIndex;
// The row of the array element of the packed varying.
unsigned int varyingRowIndex;
// The register row to which we've assigned this packed varying.
unsigned int registerRow;
size_t varyingIndex; // The column of the register row into which we've packed this varying.
unsigned int elementIndex; unsigned int registerColumn;
unsigned int rowIndex;
// Assigned after packing
unsigned int semanticIndex;
}; };
class PackedVaryingIterator final : public angle::NonCopyable class VaryingPacking final : angle::NonCopyable
{ {
public: public:
PackedVaryingIterator(const std::vector<PackedVarying> &packedVaryings); VaryingPacking(GLuint maxVaryingVectors);
class Iterator final
{
public:
Iterator(const PackedVaryingIterator &parent);
Iterator(const Iterator &) = default; bool packVaryings(gl::InfoLog &infoLog,
Iterator &operator=(const Iterator &) = delete; const std::vector<PackedVarying> &packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings);
Iterator &operator++(); struct Register
bool operator==(const Iterator &other) const; {
bool operator!=(const Iterator &other) const; Register() { data[0] = data[1] = data[2] = data[3] = false; }
const PackedVaryingRegister &operator*() const { return mRegister; } bool &operator[](unsigned int index) { return data[index]; }
void setEnd() { mRegister.varyingIndex = mParent.mPackedVaryings.size(); } bool operator[](unsigned int index) const { return data[index]; }
private: bool data[4];
const PackedVaryingIterator &mParent;
PackedVaryingRegister mRegister;
}; };
Iterator begin() const; Register &operator[](unsigned int index) { return mRegisterMap[index]; }
const Iterator &end() const; const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
private: const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
const std::vector<PackedVarying> &mPackedVaryings; unsigned int getMaxSemanticIndex() const
Iterator mEnd; {
}; return static_cast<unsigned int>(mRegisterList.size());
}
typedef const PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4]; unsigned int getRegisterCount() const;
bool PackVaryings(const gl::Caps &caps, void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata);
gl::InfoLog &infoLog,
std::vector<PackedVarying> *packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings,
unsigned int *registerCountOut);
struct SemanticInfo final struct BuiltinVarying final : angle::NonCopyable
{
struct BuiltinInfo final
{ {
BuiltinInfo(); BuiltinVarying();
std::string str() const; std::string str() const;
void enableSystem(const std::string &systemValueSemantic); void enableSystem(const std::string &systemValueSemantic);
...@@ -112,16 +116,34 @@ struct SemanticInfo final ...@@ -112,16 +116,34 @@ struct SemanticInfo final
bool systemValue; bool systemValue;
}; };
BuiltinInfo dxPosition; struct BuiltinInfo
BuiltinInfo glPosition; {
BuiltinInfo glFragCoord; BuiltinVarying dxPosition;
BuiltinInfo glPointCoord; BuiltinVarying glPosition;
BuiltinInfo glPointSize; BuiltinVarying glFragCoord;
}; BuiltinVarying glPointCoord;
BuiltinVarying glPointSize;
};
SemanticInfo GetSemanticInfo(ShaderType shaderType, const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
const ProgramD3DMetadata &programMetadata,
unsigned int startRegisters); bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; }
private:
bool packVarying(const PackedVarying &packedVarying);
bool isFree(unsigned int registerRow,
unsigned int registerColumn,
unsigned int varyingRows,
unsigned int varyingColumns) const;
void insert(unsigned int registerRow,
unsigned int registerColumn,
const PackedVarying &packedVarying);
std::vector<Register> mRegisterMap;
std::vector<PackedVaryingRegister> mRegisterList;
std::vector<BuiltinInfo> mBuiltinInfo;
};
} // namespace rx } // namespace rx
......
...@@ -3257,7 +3257,7 @@ ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data) ...@@ -3257,7 +3257,7 @@ ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data)
gl::Error Renderer11::loadExecutable(const void *function, gl::Error Renderer11::loadExecutable(const void *function,
size_t length, size_t length,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) ShaderExecutableD3D **outExecutable)
{ {
...@@ -3275,25 +3275,22 @@ gl::Error Renderer11::loadExecutable(const void *function, ...@@ -3275,25 +3275,22 @@ gl::Error Renderer11::loadExecutable(const void *function,
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result);
} }
if (transformFeedbackVaryings.size() > 0) if (!streamOutVaryings.empty())
{ {
std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration; std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) soDeclaration.reserve(streamOutVaryings.size());
for (const auto &streamOutVarying : streamOutVaryings)
{ {
const D3DVarying &varying = transformFeedbackVaryings[i]; D3D11_SO_DECLARATION_ENTRY entry = {0};
GLenum transposedType = gl::TransposeMatrixType(varying.type); entry.Stream = 0;
entry.SemanticName = streamOutVarying.semanticName.c_str();
for (unsigned int j = 0; j < varying.semanticIndexCount; j++) entry.SemanticIndex = streamOutVarying.semanticIndex;
{ entry.StartComponent = 0;
D3D11_SO_DECLARATION_ENTRY entry = { 0 }; entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
entry.Stream = 0; entry.OutputSlot = static_cast<BYTE>(
entry.SemanticName = varying.semanticName.c_str(); (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
entry.SemanticIndex = varying.semanticIndex + j; soDeclaration.push_back(entry);
entry.StartComponent = 0;
entry.ComponentCount = static_cast<BYTE>(gl::VariableColumnCount(transposedType));
entry.OutputSlot = static_cast<BYTE>((separatedOutputBuffers ? i : 0));
soDeclaration.push_back(entry);
}
} }
result = mDevice->CreateGeometryShaderWithStreamOutput( result = mDevice->CreateGeometryShaderWithStreamOutput(
...@@ -3349,7 +3346,7 @@ gl::Error Renderer11::loadExecutable(const void *function, ...@@ -3349,7 +3346,7 @@ gl::Error Renderer11::loadExecutable(const void *function,
gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL, const std::string &shaderHLSL,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) ShaderExecutableD3D **outExectuable)
...@@ -3422,7 +3419,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, ...@@ -3422,7 +3419,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
} }
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers, outExectuable); streamOutVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary); SafeRelease(binary);
if (error.isError()) if (error.isError())
......
...@@ -191,13 +191,13 @@ class Renderer11 : public RendererD3D ...@@ -191,13 +191,13 @@ class Renderer11 : public RendererD3D
gl::Error loadExecutable(const void *function, gl::Error loadExecutable(const void *function,
size_t length, size_t length,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) override; ShaderExecutableD3D **outExecutable) override;
gl::Error compileToExecutable(gl::InfoLog &infoLog, gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL, const std::string &shaderHLSL,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) override; ShaderExecutableD3D **outExectuable) override;
......
...@@ -2735,12 +2735,12 @@ ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data) ...@@ -2735,12 +2735,12 @@ ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data)
gl::Error Renderer9::loadExecutable(const void *function, gl::Error Renderer9::loadExecutable(const void *function,
size_t length, size_t length,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) ShaderExecutableD3D **outExecutable)
{ {
// Transform feedback is not supported in ES2 or D3D9 // Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0); ASSERT(streamOutVaryings.empty());
switch (type) switch (type)
{ {
...@@ -2777,13 +2777,13 @@ gl::Error Renderer9::loadExecutable(const void *function, ...@@ -2777,13 +2777,13 @@ gl::Error Renderer9::loadExecutable(const void *function,
gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL, const std::string &shaderHLSL,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) ShaderExecutableD3D **outExectuable)
{ {
// Transform feedback is not supported in ES2 or D3D9 // Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0); ASSERT(streamOutVaryings.empty());
const char *profileType = NULL; const char *profileType = NULL;
switch (type) switch (type)
...@@ -2846,7 +2846,7 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, ...@@ -2846,7 +2846,7 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
} }
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers, outExectuable); streamOutVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary); SafeRelease(binary);
if (error.isError()) if (error.isError())
......
...@@ -179,13 +179,13 @@ class Renderer9 : public RendererD3D ...@@ -179,13 +179,13 @@ class Renderer9 : public RendererD3D
gl::Error loadExecutable(const void *function, gl::Error loadExecutable(const void *function,
size_t length, size_t length,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) override; ShaderExecutableD3D **outExecutable) override;
gl::Error compileToExecutable(gl::InfoLog &infoLog, gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL, const std::string &shaderHLSL,
ShaderType type, ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings, const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers, bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds, const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) override; ShaderExecutableD3D **outExectuable) override;
......
...@@ -828,8 +828,14 @@ TEST_P(GLSLTest, MaxVaryingVec3Array) ...@@ -828,8 +828,14 @@ TEST_P(GLSLTest, MaxVaryingVec3Array)
} }
// Disabled because of a failure in D3D9 // Disabled because of a failure in D3D9
TEST_P(GLSLTest, DISABLED_MaxVaryingVec3AndOneFloat) TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
{ {
if (isD3D9())
{
std::cout << "Test disabled on D3D9." << std::endl;
return;
}
GLint maxVaryings = 0; GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
...@@ -837,8 +843,14 @@ TEST_P(GLSLTest, DISABLED_MaxVaryingVec3AndOneFloat) ...@@ -837,8 +843,14 @@ TEST_P(GLSLTest, DISABLED_MaxVaryingVec3AndOneFloat)
} }
// Disabled because of a failure in D3D9 // Disabled because of a failure in D3D9
TEST_P(GLSLTest, DISABLED_MaxVaryingVec3ArrayAndOneFloatArray) TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
{ {
if (isD3D9())
{
std::cout << "Test disabled on D3D9." << std::endl;
return;
}
GLint maxVaryings = 0; GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
...@@ -846,8 +858,14 @@ TEST_P(GLSLTest, DISABLED_MaxVaryingVec3ArrayAndOneFloatArray) ...@@ -846,8 +858,14 @@ TEST_P(GLSLTest, DISABLED_MaxVaryingVec3ArrayAndOneFloatArray)
} }
// Disabled because of a failure in D3D9 // Disabled because of a failure in D3D9
TEST_P(GLSLTest, DISABLED_TwiceMaxVaryingVec2) TEST_P(GLSLTest, TwiceMaxVaryingVec2)
{ {
if (isD3D9())
{
std::cout << "Test disabled on D3D9." << std::endl;
return;
}
GLint maxVaryings = 0; GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
...@@ -855,8 +873,14 @@ TEST_P(GLSLTest, DISABLED_TwiceMaxVaryingVec2) ...@@ -855,8 +873,14 @@ TEST_P(GLSLTest, DISABLED_TwiceMaxVaryingVec2)
} }
// Disabled because of a failure in D3D9 // Disabled because of a failure in D3D9
TEST_P(GLSLTest, DISABLED_MaxVaryingVec2Arrays) TEST_P(GLSLTest, MaxVaryingVec2Arrays)
{ {
if (isD3DSM3())
{
std::cout << "Test disabled on SM3." << std::endl;
return;
}
GLint maxVaryings = 0; GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings); glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
// //
#include "test_utils/ANGLETest.h" #include "test_utils/ANGLETest.h"
#include "Vector.h"
using namespace angle; using namespace angle;
...@@ -15,6 +16,10 @@ class TransformFeedbackTest : public ANGLETest ...@@ -15,6 +16,10 @@ class TransformFeedbackTest : public ANGLETest
{ {
protected: protected:
TransformFeedbackTest() TransformFeedbackTest()
: mProgram(0),
mTransformFeedbackBufferSize(0),
mTransformFeedbackBuffer(0),
mTransformFeedback(0)
{ {
setWindowWidth(128); setWindowWidth(128);
setWindowHeight(128); setWindowHeight(128);
...@@ -28,6 +33,44 @@ class TransformFeedbackTest : public ANGLETest ...@@ -28,6 +33,44 @@ class TransformFeedbackTest : public ANGLETest
{ {
ANGLETest::SetUp(); ANGLETest::SetUp();
glGenBuffers(1, &mTransformFeedbackBuffer);
mTransformFeedbackBufferSize = 1 << 24; // ~16MB
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, NULL,
GL_STATIC_DRAW);
glGenTransformFeedbacks(1, &mTransformFeedback);
ASSERT_GL_NO_ERROR();
}
void TearDown() override
{
if (mProgram != 0)
{
glDeleteProgram(mProgram);
mProgram = 0;
}
if (mTransformFeedbackBuffer != 0)
{
glDeleteBuffers(1, &mTransformFeedbackBuffer);
mTransformFeedbackBuffer = 0;
}
if (mTransformFeedback != 0)
{
glDeleteTransformFeedbacks(1, &mTransformFeedback);
mTransformFeedback = 0;
}
ANGLETest::TearDown();
}
void compileDefaultProgram(const std::vector<std::string> &tfVaryings, GLenum bufferMode)
{
ASSERT_EQ(0u, mProgram);
const std::string vertexShaderSource = SHADER_SOURCE const std::string vertexShaderSource = SHADER_SOURCE
( (
precision highp float; precision highp float;
...@@ -49,49 +92,24 @@ class TransformFeedbackTest : public ANGLETest ...@@ -49,49 +92,24 @@ class TransformFeedbackTest : public ANGLETest
} }
); );
mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource); mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
if (mProgram == 0) tfVaryings, bufferMode);
{ ASSERT_NE(0u, mProgram);
FAIL() << "shader compilation failed.";
}
glGenBuffers(1, &mTransformFeedbackBuffer);
mTransformFeedbackBufferSize = 1 << 24; // ~16MB
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, NULL, GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
}
void TearDown() override
{
glDeleteProgram(mProgram);
glDeleteBuffers(1, &mTransformFeedbackBuffer);
ANGLETest::TearDown();
} }
GLuint mProgram; GLuint mProgram;
size_t mTransformFeedbackBufferSize; size_t mTransformFeedbackBufferSize;
GLuint mTransformFeedbackBuffer; GLuint mTransformFeedbackBuffer;
GLuint mTransformFeedback;
}; };
TEST_P(TransformFeedbackTest, ZeroSizedViewport) TEST_P(TransformFeedbackTest, ZeroSizedViewport)
{ {
// Set the program's transform feedback varyings (just gl_Position) // Set the program's transform feedback varyings (just gl_Position)
const GLchar* transformFeedbackVaryings[] = std::vector<std::string> tfVaryings;
{ tfVaryings.push_back("gl_Position");
"gl_Position" compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
};
glTransformFeedbackVaryings(mProgram,
static_cast<GLsizei>(ArraySize(transformFeedbackVaryings)),
transformFeedbackVaryings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(mProgram);
// Re-link the program
GLint linkStatus;
glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
ASSERT_NE(linkStatus, 0);
glUseProgram(mProgram); glUseProgram(mProgram);
...@@ -137,19 +155,9 @@ TEST_P(TransformFeedbackTest, RecordAndDraw) ...@@ -137,19 +155,9 @@ TEST_P(TransformFeedbackTest, RecordAndDraw)
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
// Set the program's transform feedback varyings (just gl_Position) // Set the program's transform feedback varyings (just gl_Position)
const GLchar* transformFeedbackVaryings[] = std::vector<std::string> tfVaryings;
{ tfVaryings.push_back("gl_Position");
"gl_Position" compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
};
glTransformFeedbackVaryings(mProgram,
static_cast<GLsizei>(ArraySize(transformFeedbackVaryings)),
transformFeedbackVaryings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(mProgram);
// Re-link the program
GLint linkStatus;
glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
ASSERT_NE(linkStatus, 0);
glUseProgram(mProgram); glUseProgram(mProgram);
...@@ -223,10 +231,7 @@ TEST_P(TransformFeedbackTest, BufferBinding) ...@@ -223,10 +231,7 @@ TEST_P(TransformFeedbackTest, BufferBinding)
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
// Generate a new transform feedback and buffer // Generate a new buffer
GLuint transformFeedbackObject = 0;
glGenTransformFeedbacks(1, &transformFeedbackObject);
GLuint scratchBuffer = 0; GLuint scratchBuffer = 0;
glGenBuffers(1, &scratchBuffer); glGenBuffers(1, &scratchBuffer);
...@@ -246,7 +251,7 @@ TEST_P(TransformFeedbackTest, BufferBinding) ...@@ -246,7 +251,7 @@ TEST_P(TransformFeedbackTest, BufferBinding)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
// Check that the buffer ID for the newly bound transform feedback is zero // Check that the buffer ID for the newly bound transform feedback is zero
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackObject); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &currentBufferBinding); glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &currentBufferBinding);
EXPECT_EQ(0, currentBufferBinding); EXPECT_EQ(0, currentBufferBinding);
...@@ -270,7 +275,6 @@ TEST_P(TransformFeedbackTest, BufferBinding) ...@@ -270,7 +275,6 @@ TEST_P(TransformFeedbackTest, BufferBinding)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
// Clean up // Clean up
glDeleteTransformFeedbacks(1, &transformFeedbackObject);
glDeleteBuffers(1, &scratchBuffer); glDeleteBuffers(1, &scratchBuffer);
} }
...@@ -297,13 +301,11 @@ TEST_P(TransformFeedbackTest, VertexOnly) ...@@ -297,13 +301,11 @@ TEST_P(TransformFeedbackTest, VertexOnly)
std::vector<std::string> tfVaryings; std::vector<std::string> tfVaryings;
tfVaryings.push_back("varyingAttrib"); tfVaryings.push_back("varyingAttrib");
GLuint program = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource, mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
tfVaryings, GL_INTERLEAVED_ATTRIBS); tfVaryings, GL_INTERLEAVED_ATTRIBS);
ASSERT_NE(0u, program); ASSERT_NE(0u, mProgram);
GLuint transformFeedback; glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
glGenTransformFeedbacks(1, &transformFeedback);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
std::vector<float> attribData; std::vector<float> attribData;
...@@ -312,14 +314,14 @@ TEST_P(TransformFeedbackTest, VertexOnly) ...@@ -312,14 +314,14 @@ TEST_P(TransformFeedbackTest, VertexOnly)
attribData.push_back(static_cast<float>(cnt)); attribData.push_back(static_cast<float>(cnt));
} }
GLint attribLocation = glGetAttribLocation(program, "attrib"); GLint attribLocation = glGetAttribLocation(mProgram, "attrib");
ASSERT_NE(-1, attribLocation); ASSERT_NE(-1, attribLocation);
glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, &attribData[0]); glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, &attribData[0]);
glEnableVertexAttribArray(attribLocation); glEnableVertexAttribArray(attribLocation);
glBeginTransformFeedback(GL_TRIANGLES); glBeginTransformFeedback(GL_TRIANGLES);
drawQuad(program, "position", 0.5f); drawQuad(mProgram, "position", 0.5f);
glEndTransformFeedback(); glEndTransformFeedback();
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
...@@ -333,9 +335,6 @@ TEST_P(TransformFeedbackTest, VertexOnly) ...@@ -333,9 +335,6 @@ TEST_P(TransformFeedbackTest, VertexOnly)
EXPECT_EQ(attribData[cnt], mappedFloats[cnt]); EXPECT_EQ(attribData[cnt], mappedFloats[cnt]);
} }
glDeleteTransformFeedbacks(1, &transformFeedback);
glDeleteProgram(program);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
...@@ -381,16 +380,16 @@ TEST_P(TransformFeedbackTest, MultiplePaused) ...@@ -381,16 +380,16 @@ TEST_P(TransformFeedbackTest, MultiplePaused)
std::vector<std::string> tfVaryings; std::vector<std::string> tfVaryings;
tfVaryings.push_back("transformFeedbackOutput"); tfVaryings.push_back("transformFeedbackOutput");
GLuint program = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource, mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
tfVaryings, GL_INTERLEAVED_ATTRIBS); tfVaryings, GL_INTERLEAVED_ATTRIBS);
ASSERT_NE(program, 0u); ASSERT_NE(0u, mProgram);
glUseProgram(program); glUseProgram(mProgram);
GLint positionLocation = glGetAttribLocation(program, "position"); GLint positionLocation = glGetAttribLocation(mProgram, "position");
glDisableVertexAttribArray(positionLocation); glDisableVertexAttribArray(positionLocation);
glVertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f); glVertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
GLint tfInputLocation = glGetAttribLocation(program, "transformFeedbackInput"); GLint tfInputLocation = glGetAttribLocation(mProgram, "transformFeedbackInput");
glEnableVertexAttribArray(tfInputLocation); glEnableVertexAttribArray(tfInputLocation);
glVertexAttribPointer(tfInputLocation, 1, GL_FLOAT, false, 0, &transformFeedbackData[0]); glVertexAttribPointer(tfInputLocation, 1, GL_FLOAT, false, 0, &transformFeedbackData[0]);
...@@ -628,7 +627,79 @@ TEST_P(TransformFeedbackTest, MultiContext) ...@@ -628,7 +627,79 @@ TEST_P(TransformFeedbackTest, MultiContext)
} }
} }
// Test that when two vec2s are packed into the same register, we can still capture both of them.
TEST_P(TransformFeedbackTest, PackingBug)
{
// TODO(jmadill): With points and rasterizer discard?
const std::string &vertexShaderSource =
"#version 300 es\n"
"in vec2 inAttrib1;\n"
"in vec2 inAttrib2;\n"
"out vec2 outAttrib1;\n"
"out vec2 outAttrib2;\n"
"in vec2 position;\n"
"void main() {"
" outAttrib1 = inAttrib1;\n"
" outAttrib2 = inAttrib2;\n"
" gl_Position = vec4(position, 0, 1);\n"
"}";
const std::string &fragmentShaderSource =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 color;\n"
"void main() {\n"
" color = vec4(0);\n"
"}";
std::vector<std::string> tfVaryings;
tfVaryings.push_back("outAttrib1");
tfVaryings.push_back("outAttrib2");
mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
tfVaryings, GL_INTERLEAVED_ATTRIBS);
ASSERT_NE(0u, mProgram);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(Vector2) * 2 * 6, nullptr, GL_STREAM_DRAW);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
GLint attrib1Loc = glGetAttribLocation(mProgram, "inAttrib1");
GLint attrib2Loc = glGetAttribLocation(mProgram, "inAttrib2");
Vector2 attrib1Data[] = {Vector2(1.0, 2.0), Vector2(3.0, 4.0), Vector2(5.0, 6.0)};
Vector2 attrib2Data[] = {Vector2(11.0, 12.0), Vector2(13.0, 14.0), Vector2(15.0, 16.0)};
glEnableVertexAttribArray(attrib1Loc);
glEnableVertexAttribArray(attrib2Loc);
glVertexAttribPointer(attrib1Loc, 2, GL_FLOAT, GL_FALSE, 0, attrib1Data);
glVertexAttribPointer(attrib2Loc, 2, GL_FLOAT, GL_FALSE, 0, attrib2Data);
glBeginTransformFeedback(GL_TRIANGLES);
drawQuad(mProgram, "position", 0.5f);
glEndTransformFeedback();
ASSERT_GL_NO_ERROR();
const GLvoid *mapPointer =
glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(Vector2) * 2 * 6, GL_MAP_READ_BIT);
ASSERT_NE(nullptr, mapPointer);
const Vector2 *vecPointer = static_cast<const Vector2 *>(mapPointer);
for (unsigned int vectorIndex = 0; vectorIndex < 3; ++vectorIndex)
{
unsigned int stream1Index = vectorIndex * 2;
unsigned int stream2Index = vectorIndex * 2 + 1;
EXPECT_EQ(attrib1Data[vectorIndex], vecPointer[stream1Index]);
EXPECT_EQ(attrib2Data[vectorIndex], vecPointer[stream2Index]);
}
ASSERT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11(), ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11(), ES3_OPENGL());
} // namespace } // anonymous namespace
...@@ -298,6 +298,24 @@ bool ANGLETest::isD3D11() const ...@@ -298,6 +298,24 @@ bool ANGLETest::isD3D11() const
return (rendererString.find("Direct3D11 vs_5_0") != std::string::npos); return (rendererString.find("Direct3D11 vs_5_0") != std::string::npos);
} }
bool ANGLETest::isD3D11_FL93() const
{
std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
return (rendererString.find("Direct3D11 vs_4_0_") != std::string::npos);
}
bool ANGLETest::isD3D9() const
{
std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
return (rendererString.find("Direct3D9") != std::string::npos);
}
bool ANGLETest::isD3DSM3() const
{
std::string rendererString(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
return isD3D9() || isD3D11_FL93();
}
EGLint ANGLETest::getPlatformRenderer() const EGLint ANGLETest::getPlatformRenderer() const
{ {
assert(mEGLWindow); assert(mEGLWindow);
......
...@@ -100,6 +100,11 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters> ...@@ -100,6 +100,11 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
bool isNVidia() const; bool isNVidia() const;
// Note: FL9_3 is explicitly *not* considered D3D11. // Note: FL9_3 is explicitly *not* considered D3D11.
bool isD3D11() const; bool isD3D11() const;
bool isD3D11_FL93() const;
// Is a D3D9-class renderer.
bool isD3D9() const;
// Is D3D9 or SM9_3 renderer.
bool isD3DSM3() const;
EGLint getPlatformRenderer() const; EGLint getPlatformRenderer() const;
private: private:
......
...@@ -19,6 +19,22 @@ Vector2::Vector2(float x, float y) : x(x), y(y) ...@@ -19,6 +19,22 @@ Vector2::Vector2(float x, float y) : x(x), y(y)
{ {
} }
bool Vector2::operator==(const Vector2 &vec) const
{
return x == vec.x && y == vec.y;
}
bool Vector2::operator!=(const Vector2 &vec) const
{
return !(*this == vec);
}
std::ostream &operator<<(std::ostream &stream, const Vector2 &vec)
{
stream << "(" << vec.x << "," << vec.y << ")";
return stream;
}
float Vector2::length(const Vector2 &vec) float Vector2::length(const Vector2 &vec)
{ {
float lenSquared = lengthSquared(vec); float lenSquared = lengthSquared(vec);
......
...@@ -10,11 +10,16 @@ ...@@ -10,11 +10,16 @@
#ifndef UTIL_VECTOR_H #ifndef UTIL_VECTOR_H
#define UTIL_VECTOR_H #define UTIL_VECTOR_H
#include <ostream>
struct Vector2 struct Vector2
{ {
Vector2(); Vector2();
Vector2(float x, float y); Vector2(float x, float y);
bool operator==(const Vector2 &vec) const;
bool operator!=(const Vector2 &vec) const;
static float length(const Vector2 &vec); static float length(const Vector2 &vec);
static float lengthSquared(const Vector2 &vec); static float lengthSquared(const Vector2 &vec);
...@@ -26,6 +31,8 @@ struct Vector2 ...@@ -26,6 +31,8 @@ struct Vector2
float x, y; float x, y;
}; };
std::ostream &operator<<(std::ostream &stream, const Vector2 &vec);
struct Vector3 struct Vector3
{ {
Vector3(); Vector3();
......
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