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
return *variableList;
}
} // anonymous namespace
// true if varying x has a higher priority in packing than 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)
return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
}
} // anonymous namespace
Shader::Data::Data(GLenum shaderType) : mShaderType(shaderType), mShaderVersion(100)
{
}
......
......@@ -137,6 +137,7 @@ class Shader : angle::NonCopyable
ResourceManager *mResourceManager;
};
bool CompareVarying(const sh::Varying &x, const sh::Varying &y);
}
#endif // LIBANGLE_SHADER_H_
......@@ -37,8 +37,8 @@ namespace rx
{
struct PackedVarying;
class ProgramD3DMetadata;
struct SemanticInfo;
class ShaderD3D;
class VaryingPacking;
struct PixelShaderOutputVariable
{
......@@ -65,19 +65,11 @@ class DynamicHLSL : angle::NonCopyable
bool generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData,
const ProgramD3DMetadata &programMetadata,
gl::InfoLog &infoLog,
unsigned int registerCount,
const VaryingPacking &varyingPacking,
std::string *pixelHLSL,
std::string *vertexHLSL,
const std::vector<PackedVarying> &packedVaryings,
std::vector<D3DVarying> *d3dVaryingsOut) const;
std::string *vertexHLSL) const;
std::string generateGeometryShaderPreamble(
const gl::Data &data,
const gl::Program::Data &programData,
const ProgramD3DMetadata &programMetadata,
unsigned int registers,
const std::vector<PackedVarying> &packedVaryings) const;
std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const;
std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::Data &data,
......@@ -92,20 +84,11 @@ class DynamicHLSL : angle::NonCopyable
private:
RendererD3D *const mRenderer;
void generateVaryingLinkHLSL(const gl::Caps &caps,
bool programUsesPointSize,
const SemanticInfo &info,
const std::vector<PackedVarying> &packedVaryings,
void generateVaryingLinkHLSL(ShaderType shaderType,
const VaryingPacking &varyingPacking,
std::stringstream &linkStream) const;
void generateVaryingHLSL(const gl::Caps &caps,
const std::vector<PackedVarying> &varyings,
bool programUsesPointSize,
void generateVaryingHLSL(const VaryingPacking &varyingPacking,
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
static std::string decorateVariable(const std::string &name);
......
......@@ -80,26 +80,21 @@ struct D3DUniformBlock
unsigned int psRegisterIndex;
};
struct D3DVarying
struct D3DVarying final
{
D3DVarying();
D3DVarying(const std::string &name,
GLenum type,
GLsizei size,
const std::string &semanticName,
unsigned int semanticIndex,
unsigned int semanticIndexCount);
// Original GL name
std::string name;
D3DVarying(const std::string &semanticNameIn,
unsigned int semanticIndexIn,
unsigned int componentCountIn,
unsigned int outputSlotIn);
GLenum type;
GLsizei size;
D3DVarying(const D3DVarying &) = default;
D3DVarying &operator=(const D3DVarying &) = default;
// DirectX semantic information
std::string semanticName;
unsigned int semanticIndex;
unsigned int semanticIndexCount;
unsigned int componentCount;
unsigned int outputSlot;
};
class ProgramD3DMetadata : angle::NonCopyable
......@@ -336,7 +331,7 @@ class ProgramD3D : public ProgramImpl
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 *getD3DUniformFromLocation(GLint location);
......@@ -394,7 +389,7 @@ class ProgramD3D : public ProgramImpl
VertexExecutable::Signature mCachedVertexSignature;
gl::InputLayout mCachedInputLayout;
std::vector<D3DVarying> mTransformFeedbackD3DVaryings;
std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms;
std::vector<D3DUniformBlock> mD3DUniformBlocks;
......
......@@ -56,7 +56,8 @@ enum ShaderType
{
SHADER_VERTEX,
SHADER_PIXEL,
SHADER_GEOMETRY
SHADER_GEOMETRY,
SHADER_TYPE_MAX
};
struct DeviceIdentifier
......@@ -206,13 +207,13 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual gl::Error loadExecutable(const void *function,
size_t length,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) = 0;
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) = 0;
......
......@@ -19,88 +19,92 @@ class ProgramD3DMetadata;
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; }
PackedVarying(const sh::Varying &varyingIn) : varying(&varyingIn), vertexOnly(false) {}
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;
};
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 &operator=(const PackedVaryingRegister &) = default;
unsigned int registerIndex(const gl::Caps &caps,
const std::vector<PackedVarying> &packedVaryings) const;
bool operator<(const PackedVaryingRegister &other) 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;
unsigned int elementIndex;
unsigned int rowIndex;
// The column of the register row into which we've packed this varying.
unsigned int registerColumn;
// Assigned after packing
unsigned int semanticIndex;
};
class PackedVaryingIterator final : public angle::NonCopyable
class VaryingPacking final : angle::NonCopyable
{
public:
PackedVaryingIterator(const std::vector<PackedVarying> &packedVaryings);
class Iterator final
{
public:
Iterator(const PackedVaryingIterator &parent);
VaryingPacking(GLuint maxVaryingVectors);
Iterator(const Iterator &) = default;
Iterator &operator=(const Iterator &) = delete;
bool packVaryings(gl::InfoLog &infoLog,
const std::vector<PackedVarying> &packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings);
Iterator &operator++();
bool operator==(const Iterator &other) const;
bool operator!=(const Iterator &other) const;
struct Register
{
Register() { data[0] = data[1] = data[2] = data[3] = false; }
const PackedVaryingRegister &operator*() const { return mRegister; }
void setEnd() { mRegister.varyingIndex = mParent.mPackedVaryings.size(); }
bool &operator[](unsigned int index) { return data[index]; }
bool operator[](unsigned int index) const { return data[index]; }
private:
const PackedVaryingIterator &mParent;
PackedVaryingRegister mRegister;
bool data[4];
};
Iterator begin() const;
const Iterator &end() const;
Register &operator[](unsigned int index) { return mRegisterMap[index]; }
const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
private:
const std::vector<PackedVarying> &mPackedVaryings;
Iterator mEnd;
};
typedef const PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4];
const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
unsigned int getMaxSemanticIndex() const
{
return static_cast<unsigned int>(mRegisterList.size());
}
unsigned int getRegisterCount() const;
bool PackVaryings(const gl::Caps &caps,
gl::InfoLog &infoLog,
std::vector<PackedVarying> *packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings,
unsigned int *registerCountOut);
void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata);
struct SemanticInfo final
{
struct BuiltinInfo final
struct BuiltinVarying final : angle::NonCopyable
{
BuiltinInfo();
BuiltinVarying();
std::string str() const;
void enableSystem(const std::string &systemValueSemantic);
......@@ -112,16 +116,34 @@ struct SemanticInfo final
bool systemValue;
};
BuiltinInfo dxPosition;
BuiltinInfo glPosition;
BuiltinInfo glFragCoord;
BuiltinInfo glPointCoord;
BuiltinInfo glPointSize;
};
struct BuiltinInfo
{
BuiltinVarying dxPosition;
BuiltinVarying glPosition;
BuiltinVarying glFragCoord;
BuiltinVarying glPointCoord;
BuiltinVarying glPointSize;
};
SemanticInfo GetSemanticInfo(ShaderType shaderType,
const ProgramD3DMetadata &programMetadata,
unsigned int startRegisters);
const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
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
......
......@@ -3257,7 +3257,7 @@ ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data)
gl::Error Renderer11::loadExecutable(const void *function,
size_t length,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable)
{
......@@ -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);
}
if (transformFeedbackVaryings.size() > 0)
if (!streamOutVaryings.empty())
{
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];
GLenum transposedType = gl::TransposeMatrixType(varying.type);
for (unsigned int j = 0; j < varying.semanticIndexCount; j++)
{
D3D11_SO_DECLARATION_ENTRY entry = { 0 };
entry.Stream = 0;
entry.SemanticName = varying.semanticName.c_str();
entry.SemanticIndex = varying.semanticIndex + j;
entry.StartComponent = 0;
entry.ComponentCount = static_cast<BYTE>(gl::VariableColumnCount(transposedType));
entry.OutputSlot = static_cast<BYTE>((separatedOutputBuffers ? i : 0));
soDeclaration.push_back(entry);
}
D3D11_SO_DECLARATION_ENTRY entry = {0};
entry.Stream = 0;
entry.SemanticName = streamOutVarying.semanticName.c_str();
entry.SemanticIndex = streamOutVarying.semanticIndex;
entry.StartComponent = 0;
entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
entry.OutputSlot = static_cast<BYTE>(
(separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
soDeclaration.push_back(entry);
}
result = mDevice->CreateGeometryShaderWithStreamOutput(
......@@ -3349,7 +3346,7 @@ gl::Error Renderer11::loadExecutable(const void *function,
gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable)
......@@ -3422,7 +3419,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
}
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
streamOutVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary);
if (error.isError())
......
......@@ -191,13 +191,13 @@ class Renderer11 : public RendererD3D
gl::Error loadExecutable(const void *function,
size_t length,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) override;
gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) override;
......
......@@ -2735,12 +2735,12 @@ ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data)
gl::Error Renderer9::loadExecutable(const void *function,
size_t length,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
ASSERT(streamOutVaryings.empty());
switch (type)
{
......@@ -2777,13 +2777,13 @@ gl::Error Renderer9::loadExecutable(const void *function,
gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
ASSERT(streamOutVaryings.empty());
const char *profileType = NULL;
switch (type)
......@@ -2846,7 +2846,7 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
}
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
streamOutVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary);
if (error.isError())
......
......@@ -179,13 +179,13 @@ class Renderer9 : public RendererD3D
gl::Error loadExecutable(const void *function,
size_t length,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) override;
gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
ShaderType type,
const std::vector<D3DVarying> &transformFeedbackVaryings,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) override;
......
......@@ -828,8 +828,14 @@ TEST_P(GLSLTest, MaxVaryingVec3Array)
}
// 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;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
......@@ -837,8 +843,14 @@ TEST_P(GLSLTest, DISABLED_MaxVaryingVec3AndOneFloat)
}
// 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;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
......@@ -846,8 +858,14 @@ TEST_P(GLSLTest, DISABLED_MaxVaryingVec3ArrayAndOneFloatArray)
}
// 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;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
......@@ -855,8 +873,14 @@ TEST_P(GLSLTest, DISABLED_TwiceMaxVaryingVec2)
}
// 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;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
......
......@@ -298,6 +298,24 @@ bool ANGLETest::isD3D11() const
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
{
assert(mEGLWindow);
......
......@@ -100,6 +100,11 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
bool isNVidia() const;
// Note: FL9_3 is explicitly *not* considered D3D11.
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;
private:
......
......@@ -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 lenSquared = lengthSquared(vec);
......
......@@ -10,11 +10,16 @@
#ifndef UTIL_VECTOR_H
#define UTIL_VECTOR_H
#include <ostream>
struct Vector2
{
Vector2();
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 lengthSquared(const Vector2 &vec);
......@@ -26,6 +31,8 @@ struct Vector2
float x, y;
};
std::ostream &operator<<(std::ostream &stream, const Vector2 &vec);
struct 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