Re-land "Compute packed varyings in ProgramD3D only."
Instead of storing varying information in the shader, use a temporary
set when linking a D3D program. This also means we won't have to
modify information in the Shader object when linking a D3D program.
This completes the refactoring for PackedVaryings.
Re-land with fix for missing init of PackedVarying::vertexOnly.
BUG=angleproject:1123
Change-Id: If110809c3817d88b0370ac575d739d7385b067d9
Reviewed-on: https://chromium-review.googlesource.com/296731
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 942efa4..9684320 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -236,8 +236,7 @@
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Returns the number of used varying registers, or -1 if unsuccesful
int DynamicHLSL::packVaryings(InfoLog &infoLog,
- ShaderD3D *fragmentShader,
- ShaderD3D *vertexShader,
+ std::vector<PackedVarying> *packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings)
{
// TODO (geofflang): Use context's caps
@@ -245,17 +244,11 @@
VaryingPacking packing = {};
- vertexShader->resetVaryingsRegisterAssignment();
- fragmentShader->resetVaryingsRegisterAssignment();
+ std::set<std::string> uniqueVaryingNames;
- std::set<std::string> packedVaryings;
-
- std::vector<PackedVarying> &vertexVaryings = vertexShader->getPackedVaryings();
- std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getPackedVaryings();
- for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++)
+ for (PackedVarying &packedVarying : *packedVaryings)
{
- PackedVarying *packedVarying = &fragmentVaryings[varyingIndex];
- const sh::Varying &varying = *packedVarying->varying;
+ const sh::Varying &varying = *packedVarying.varying;
// Do not assign registers to built-in or unreferenced varyings
if (varying.isBuiltIn() || !varying.staticUse)
@@ -263,9 +256,11 @@
continue;
}
- if (PackVarying(packedVarying, maxVaryingVectors, packing))
+ ASSERT(uniqueVaryingNames.count(varying.name) == 0);
+
+ if (PackVarying(&packedVarying, maxVaryingVectors, packing))
{
- packedVaryings.insert(varying.name);
+ uniqueVaryingNames.insert(varying.name);
}
else
{
@@ -274,26 +269,24 @@
}
}
- for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
+ for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
{
- const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
-
- if (transformFeedbackVarying == "gl_Position" || transformFeedbackVarying == "gl_PointSize")
+ if (transformFeedbackVaryingName == "gl_Position" ||
+ transformFeedbackVaryingName == "gl_PointSize")
{
// do not pack builtin XFB varyings
continue;
}
- if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
+ if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0)
{
bool found = false;
- for (unsigned int varyingIndex = 0; varyingIndex < vertexVaryings.size(); varyingIndex++)
+ for (PackedVarying &packedVarying : *packedVaryings)
{
- PackedVarying *packedVarying = &vertexVaryings[varyingIndex];
- const sh::Varying &varying = *packedVarying->varying;
- if (transformFeedbackVarying == varying.name)
+ const sh::Varying &varying = *packedVarying.varying;
+ if (transformFeedbackVaryingName == varying.name)
{
- if (!PackVarying(packedVarying, maxVaryingVectors, packing))
+ if (!PackVarying(&packedVarying, maxVaryingVectors, packing))
{
infoLog << "Could not pack varying " << varying.name;
return -1;
@@ -306,8 +299,7 @@
if (!found)
{
- infoLog << "Transform feedback varying "
- << transformFeedbackVarying
+ infoLog << "Transform feedback varying " << transformFeedbackVaryingName
<< " does not exist in the vertex shader.";
return -1;
}
@@ -328,13 +320,12 @@
return registers;
}
-std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const
+std::string DynamicHLSL::generateVaryingHLSL(const std::vector<PackedVarying> &varyings,
+ bool shaderUsesPointSize) const
{
- std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize);
+ std::string varyingSemantic = getVaryingSemantic(shaderUsesPointSize);
std::string varyingHLSL;
- const std::vector<PackedVarying> &varyings = shader->getPackedVaryings();
-
for (const PackedVarying &packedVarying : varyings)
{
if (!packedVarying.registerAssigned())
@@ -735,12 +726,13 @@
}
}
-void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader,
+void DynamicHLSL::storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings,
+ bool shaderUsesPointSize,
std::vector<LinkedVarying> *linkedVaryings) const
{
- const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize);
+ const std::string &varyingSemantic = getVaryingSemantic(shaderUsesPointSize);
- for (const PackedVarying &packedVarying : vertexShader->getPackedVaryings())
+ for (const PackedVarying &packedVarying : packedVaryings)
{
if (packedVarying.registerAssigned())
{
@@ -763,6 +755,7 @@
int registers,
std::string &pixelHLSL,
std::string &vertexHLSL,
+ const std::vector<PackedVarying> &packedVaryings,
std::vector<LinkedVarying> *linkedVaryings,
std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
bool *outUsesFragDepth) const
@@ -807,7 +800,7 @@
return false;
}
- const std::string &varyingHLSL = generateVaryingHLSL(vertexShader);
+ const std::string &varyingHLSL = generateVaryingHLSL(packedVaryings, usesPointSize);
// 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.
@@ -820,7 +813,7 @@
usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord),
(!useInstancedPointSpriteEmulation && usesPointSize), false);
- storeUserLinkedVaryings(vertexShader, linkedVaryings);
+ storeUserLinkedVaryings(packedVaryings, usesPointSize, linkedVaryings);
storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings);
// Instanced PointSprite emulation requires additional entries originally generated in the
@@ -881,8 +874,7 @@
vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
}
- const std::vector<PackedVarying> &vertexVaryings = vertexShader->getPackedVaryings();
- for (const PackedVarying &packedVarying : vertexVaryings)
+ for (const PackedVarying &packedVarying : packedVaryings)
{
if (!packedVarying.registerAssigned())
{
@@ -1051,8 +1043,7 @@
}
}
- const std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getPackedVaryings();
- for (const PackedVarying &packedVarying : fragmentVaryings)
+ for (const PackedVarying &packedVarying : packedVaryings)
{
const sh::Varying &varying = *packedVarying.varying;
@@ -1062,6 +1053,10 @@
continue;
}
+ // Don't reference VS-only transform feedback varyings in the PS.
+ if (packedVarying.vertexOnly)
+ continue;
+
ASSERT(!varying.isBuiltIn());
for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
{
@@ -1128,21 +1123,22 @@
return true;
}
-std::string DynamicHLSL::generateGeometryShaderHLSL(int registers,
- const ShaderD3D *fragmentShader,
- const ShaderD3D *vertexShader) const
+std::string DynamicHLSL::generateGeometryShaderHLSL(
+ int registers,
+ const ShaderD3D *fragmentShader,
+ const std::vector<PackedVarying> &packedVaryings) const
{
// for now we only handle point sprite emulation
- ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
- return generatePointSpriteHLSL(registers, fragmentShader, vertexShader);
+ ASSERT(mRenderer->getMajorShaderModel() >= 4);
+ return generatePointSpriteHLSL(registers, fragmentShader, packedVaryings);
}
-std::string DynamicHLSL::generatePointSpriteHLSL(int registers,
- const ShaderD3D *fragmentShader,
- const ShaderD3D *vertexShader) const
+std::string DynamicHLSL::generatePointSpriteHLSL(
+ int registers,
+ const ShaderD3D *fragmentShader,
+ const std::vector<PackedVarying> &packedVaryings) const
{
ASSERT(registers >= 0);
- ASSERT(vertexShader->mUsesPointSize);
ASSERT(mRenderer->getMajorShaderModel() >= 4);
std::string geomHLSL;
@@ -1152,7 +1148,8 @@
const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord,
fragmentShader->mUsesPointCoord, true, false);
- std::string varyingHLSL = generateVaryingHLSL(vertexShader);
+ // If we're generating the geometry shader, we assume the vertex shader uses point size.
+ std::string varyingHLSL = generateVaryingHLSL(packedVaryings, true);
std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL);
std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL);
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/libANGLE/renderer/d3d/DynamicHLSL.h
index 9c91083..4529033 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.h
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -46,14 +46,36 @@
size_t outputIndex;
};
+struct PackedVarying
+{
+ PackedVarying(const sh::Varying &varyingIn)
+ : 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;
+
+ // 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.
+ bool vertexOnly;
+};
+
class DynamicHLSL : angle::NonCopyable
{
public:
explicit DynamicHLSL(RendererD3D *const renderer);
int packVaryings(gl::InfoLog &infoLog,
- ShaderD3D *fragmentShader,
- ShaderD3D *vertexShader,
+ std::vector<PackedVarying> *packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings);
std::string generateVertexShaderForInputLayout(const std::string &sourceShader,
const gl::InputLayout &inputLayout,
@@ -66,13 +88,14 @@
int registers,
std::string &pixelHLSL,
std::string &vertexHLSL,
+ const std::vector<PackedVarying> &packedVaryings,
std::vector<gl::LinkedVarying> *linkedVaryings,
std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
bool *outUsesFragDepth) const;
std::string generateGeometryShaderHLSL(int registers,
const ShaderD3D *fragmentShader,
- const ShaderD3D *vertexShader) const;
+ const std::vector<PackedVarying> &packedVaryings) const;
private:
RendererD3D *const mRenderer;
@@ -83,12 +106,15 @@
SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord,
bool pointSize, bool pixelShader) const;
std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const;
- std::string generateVaryingHLSL(const ShaderD3D *shader) const;
- void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
+ std::string generateVaryingHLSL(const std::vector<PackedVarying> &varyings,
+ bool shaderUsesPointSize) const;
+ void storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings,
+ bool shaderUsesPointSize,
+ std::vector<gl::LinkedVarying> *linkedVaryings) const;
void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
std::string generatePointSpriteHLSL(int registers,
const ShaderD3D *fragmentShader,
- const ShaderD3D *vertexShader) const;
+ const std::vector<PackedVarying> &packedVaryings) const;
// Prepend an underscore
static std::string decorateVariable(const std::string &name);
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp
new file mode 100644
index 0000000..ea7a331
--- /dev/null
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp
@@ -0,0 +1,30 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicHLSL unittests:
+// Tests for DynamicHLSL and related classes.
+//
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+
+using namespace rx;
+
+namespace
+{
+
+TEST(PackedVarying, DefaultInitialization)
+{
+ sh::Varying defaultVarying;
+ PackedVarying pv(defaultVarying);
+
+ EXPECT_EQ(&defaultVarying, pv.varying);
+ EXPECT_EQ(GL_INVALID_INDEX, pv.registerIndex);
+ EXPECT_EQ(0, pv.columnIndex);
+ EXPECT_FALSE(pv.vertexOnly);
+}
+
+} // anonymous namespace
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index daa7779..6d1d46e 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -127,37 +127,48 @@
const ProgramD3D::SemanticIndexArray *originalIndices;
};
-bool LinkVaryingRegisters(gl::InfoLog &infoLog,
- ShaderD3D *vertexShaderD3D,
- ShaderD3D *fragmentShaderD3D)
+std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
+ const gl::Shader &fragmentShader,
+ const std::vector<std::string> &tfVaryings)
{
- for (PackedVarying &input : fragmentShaderD3D->getPackedVaryings())
+ std::vector<PackedVarying> packedVaryings;
+
+ for (const sh::Varying &output : vertexShader.getVaryings())
{
- bool matched = false;
+ bool packed = false;
// Built-in varyings obey special rules
- if (input.varying->isBuiltIn())
+ if (output.isBuiltIn())
{
continue;
}
- for (PackedVarying &output : vertexShaderD3D->getPackedVaryings())
+ for (const sh::Varying &input : fragmentShader.getVaryings())
{
- if (output.varying->name == input.varying->name)
+ if (output.name == input.name)
{
- output.registerIndex = input.registerIndex;
- output.columnIndex = input.columnIndex;
-
- matched = true;
+ packedVaryings.push_back(PackedVarying(input));
+ packed = true;
break;
}
}
- // We permit unmatched, unreferenced varyings
- ASSERT(matched || !input.varying->staticUse);
+ // Keep Transform FB varyings in the merged list always.
+ if (!packed)
+ {
+ for (const std::string &tfVarying : tfVaryings)
+ {
+ if (tfVarying == output.name)
+ {
+ packedVaryings.push_back(PackedVarying(output));
+ packedVaryings.back().vertexOnly = true;
+ break;
+ }
+ }
+ }
}
- return true;
+ return packedVaryings;
}
} // anonymous namespace
@@ -1048,9 +1059,10 @@
return gl::Error(GL_NO_ERROR);
}
-LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, int registers)
+LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
+ int registers,
+ const std::vector<PackedVarying> &packedVaryings)
{
- const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
const gl::InputLayout &defaultInputLayout =
@@ -1072,7 +1084,8 @@
if (usesGeometryShader())
{
- std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
+ std::string geometryHLSL =
+ mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings);
error = mRenderer->compileToExecutable(
infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
@@ -1085,6 +1098,8 @@
}
#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
+
if (usesGeometryShader() && mGeometryExecutable)
{
// Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
@@ -1136,8 +1151,11 @@
}
}
+ std::vector<PackedVarying> packedVaryings =
+ MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
+
// Map the varyings to the register file
- int registers = mDynamicHLSL->packVaryings(infoLog, fragmentShaderD3D, vertexShaderD3D,
+ int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings,
mData.getTransformFeedbackVaryingNames());
if (registers < 0)
@@ -1145,12 +1163,10 @@
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
- LinkVaryingRegisters(infoLog, vertexShaderD3D, fragmentShaderD3D);
-
std::vector<gl::LinkedVarying> linkedVaryings;
if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL,
- mVertexHLSL, &linkedVaryings, &mPixelShaderKey,
- &mUsesFragDepth))
+ mVertexHLSL, packedVaryings, &linkedVaryings,
+ &mPixelShaderKey, &mUsesFragDepth))
{
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
@@ -1168,7 +1184,7 @@
gatherTransformFeedbackVaryings(linkedVaryings);
- LinkResult result = compileProgramExecutables(infoLog, registers);
+ LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
if (result.error.isError() || !result.linkSuccess)
{
infoLog << "Failed to create D3D shaders.";
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/libANGLE/renderer/d3d/ProgramD3D.h
index 37a476f..9ce3b0d 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -207,7 +207,9 @@
sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
bool inRowMajorLayout);
- LinkResult compileProgramExecutables(gl::InfoLog &infoLog, int registers);
+ LinkResult compileProgramExecutables(gl::InfoLog &infoLog,
+ int registers,
+ const std::vector<PackedVarying> &packedVaryings);
void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
diff --git a/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/libANGLE/renderer/d3d/ShaderD3D.cpp
index f71250e..0a3e8e5 100644
--- a/src/libANGLE/renderer/d3d/ShaderD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -110,11 +110,6 @@
mVaryings = *varyings;
- for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++)
- {
- mPackedVaryings.push_back(PackedVarying(mVaryings[varyingIndex]));
- }
-
mUsesMultipleRenderTargets = mTranslatedSource.find("GL_USES_MRT") != std::string::npos;
mUsesFragColor = mTranslatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
mUsesFragData = mTranslatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
@@ -131,14 +126,6 @@
}
}
-void ShaderD3D::resetVaryingsRegisterAssignment()
-{
- for (size_t varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
- {
- mPackedVaryings[varyingIndex].resetRegisterAssignment();
- }
-}
-
// initialize/clean up previous state
void ShaderD3D::uncompile()
{
diff --git a/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/libANGLE/renderer/d3d/ShaderD3D.h
index 9cdd541..b6630f2 100644
--- a/src/libANGLE/renderer/d3d/ShaderD3D.h
+++ b/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -20,24 +20,6 @@
class DynamicHLSL;
class RendererD3D;
-struct PackedVarying
-{
- PackedVarying(const sh::Varying &varyingIn)
- : varying(&varyingIn), registerIndex(GL_INVALID_INDEX), columnIndex(0)
- {
- }
-
- bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
-
- void resetRegisterAssignment() { registerIndex = GL_INVALID_INDEX; }
-
- const sh::Varying *varying;
-
- // TODO(jmadill): Make these D3D-only or otherwise clearly separate from GL.
- unsigned int registerIndex; // Assigned during link
- unsigned int columnIndex; // Assigned during link, defaults to 0
-};
-
class ShaderD3D : public ShaderImpl
{
friend class DynamicHLSL;
@@ -51,7 +33,6 @@
// D3D-specific methods
virtual void uncompile();
- void resetVaryingsRegisterAssignment();
unsigned int getUniformRegister(const std::string &uniformName) const;
unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
void appendDebugInfo(const std::string &info) { mDebugInfo += info; }
@@ -68,11 +49,6 @@
virtual bool compile(gl::Compiler *compiler, const std::string &source);
- const std::vector<PackedVarying> &getPackedVaryings() const { return mPackedVaryings; }
-
- // TODO(jmadill): remove this
- std::vector<PackedVarying> &getPackedVaryings() { return mPackedVaryings; }
-
private:
void compileToHLSL(ShHandle compiler, const std::string &source);
void parseVaryings(ShHandle compiler);
@@ -100,7 +76,6 @@
std::map<std::string, unsigned int> mUniformRegisterMap;
std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
RendererD3D *mRenderer;
- std::vector<PackedVarying> mPackedVaryings;
};
}
diff --git a/src/tests/angle_unittests.gypi b/src/tests/angle_unittests.gypi
index 22fbd91..3021909 100644
--- a/src/tests/angle_unittests.gypi
+++ b/src/tests/angle_unittests.gypi
@@ -75,8 +75,10 @@
'<(angle_path)/src/tests/test_utils/compiler_test.cpp',
'<(angle_path)/src/tests/test_utils/compiler_test.h',
],
+ # TODO(jmadill): should probably call this windows sources
'angle_unittests_hlsl_sources':
[
+ '<(angle_path)/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp',
'<(angle_path)/src/tests/compiler_tests/UnrollFlatten_test.cpp',
],
},
diff --git a/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/tests/gl_tests/TransformFeedbackTest.cpp
index 5b9cdd5..23b5bf5 100644
--- a/src/tests/gl_tests/TransformFeedbackTest.cpp
+++ b/src/tests/gl_tests/TransformFeedbackTest.cpp
@@ -264,6 +264,71 @@
glDeleteBuffers(1, &scratchBuffer);
}
+// Test that we can capture varyings only used in the vertex shader.
+TEST_P(TransformFeedbackTest, VertexOnly)
+{
+ const std::string &vertexShaderSource =
+ "#version 300 es\n"
+ "in vec2 position;\n"
+ "in float attrib;\n"
+ "out float varyingAttrib;\n"
+ "void main() {\n"
+ " gl_Position = vec4(position, 0, 1);\n"
+ " varyingAttrib = attrib;\n"
+ "}";
+
+ const std::string &fragmentShaderSource =
+ "#version 300 es\n"
+ "out mediump vec4 color;\n"
+ "void main() {\n"
+ " color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ "}";
+
+ std::vector<std::string> tfVaryings;
+ tfVaryings.push_back("varyingAttrib");
+
+ GLuint program = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+ tfVaryings, GL_INTERLEAVED_ATTRIBS);
+ ASSERT_NE(0u, program);
+
+ GLuint transformFeedback;
+ glGenTransformFeedbacks(1, &transformFeedback);
+ glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+
+ std::vector<float> attribData;
+ for (unsigned int cnt = 0; cnt < 100; ++cnt)
+ {
+ attribData.push_back(static_cast<float>(cnt));
+ }
+
+ GLint attribLocation = glGetAttribLocation(program, "attrib");
+ ASSERT_NE(-1, attribLocation);
+
+ glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, &attribData[0]);
+ glEnableVertexAttribArray(attribLocation);
+
+ glBeginTransformFeedback(GL_TRIANGLES);
+ drawQuad(program, "position", 0.5f);
+ glEndTransformFeedback();
+ ASSERT_GL_NO_ERROR();
+
+ GLvoid *mappedBuffer =
+ glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(float) * 6, GL_MAP_READ_BIT);
+ ASSERT_NE(nullptr, mappedBuffer);
+
+ float *mappedFloats = static_cast<float *>(mappedBuffer);
+ for (unsigned int cnt = 0; cnt < 6; ++cnt)
+ {
+ EXPECT_EQ(attribData[cnt], mappedFloats[cnt]);
+ }
+
+ glDeleteTransformFeedbacks(1, &transformFeedback);
+ glDeleteProgram(program);
+
+ EXPECT_GL_NO_ERROR();
+}
+
// 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());