Commit 192745a7 by Jamie Madill Committed by Commit Bot

Add varying packing validation for WebGL.

This CL moves the varying packing from the D3D layer up to Program. This is necessary for WebGL validation, and gives us consistency for the various back-ends. There may be some additional cleanup work on the VaryingPacking class, because it does some work that is D3D- specific. WebGL requires strict varying packing. Instead of allowing success unconditionally, it's an explicit error to succeed to pack a set of varyings that the sample algorithm would fail to pack. Introduce a new packing mode option to the varying packing class to handle this different packing style, while keeping our old more relaxed packing method for ES code. BUG=angleproject:1675 Change-Id: I674ae685ba573cc2ad7d9dfb7441efa8cb2d55fc Reviewed-on: https://chromium-review.googlesource.com/423254 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 4eee74de
......@@ -313,10 +313,6 @@ static_library("libANGLE") {
defines += [ "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " + "\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }" ]
}
if (angle_enable_hlsl) {
sources += rebase_path(gles_gypi.libangle_d3d_hlsl_sources, ".", "src")
}
if (angle_enable_d3d9) {
sources += rebase_path(gles_gypi.libangle_d3d9_sources, ".", "src")
libs += [ "d3d9.lib" ]
......
......@@ -49,6 +49,7 @@ class Buffer;
class Framebuffer;
struct UniformBlock;
struct LinkedUniform;
struct PackedVarying;
extern const char * const g_fakepath;
......@@ -386,6 +387,16 @@ class Program final : angle::NonCopyable, public LabeledObject
std::unordered_map<std::string, GLuint> mBindings;
};
struct VaryingRef
{
const sh::Varying *get() const { return vertex ? vertex : fragment; }
const sh::Varying *vertex = nullptr;
const sh::Varying *fragment = nullptr;
};
using MergedVaryings = std::map<std::string, VaryingRef>;
void unlink(bool destroy = false);
void resetUniformBlockBindings();
......@@ -399,7 +410,7 @@ class Program final : angle::NonCopyable, public LabeledObject
const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
InfoLog &infoLog) const;
bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps);
bool linkVaryings(InfoLog &infoLog, const Shader *vertexShader, const Shader *fragmentShader) const;
bool linkVaryings(InfoLog &infoLog) const;
bool validateVertexAndFragmentUniforms(InfoLog &infoLog) const;
bool linkUniforms(InfoLog &infoLog, const Caps &caps, const Bindings &uniformBindings);
bool indexUniforms(InfoLog &infoLog, const Caps &caps, const Bindings &uniformBindings);
......@@ -419,14 +430,15 @@ class Program final : angle::NonCopyable, public LabeledObject
const sh::Varying &fragmentVarying,
int shaderVersion);
bool linkValidateTransformFeedback(InfoLog &infoLog,
const std::vector<const sh::Varying *> &linkedVaryings,
const MergedVaryings &linkedVaryings,
const Caps &caps) const;
void gatherTransformFeedbackVaryings(const std::vector<const sh::Varying *> &varyings);
void gatherTransformFeedbackVaryings(const MergedVaryings &varyings);
bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
void defineOutputVariables(Shader *fragmentShader);
std::vector<const sh::Varying *> getMergedVaryings() const;
MergedVaryings getMergedVaryings() const;
std::vector<PackedVarying> getPackedVaryings(const MergedVaryings &mergedVaryings) const;
void linkOutputVariables();
bool flattenUniformsAndCheckCapsForShader(const Shader &shader,
......
......@@ -4,46 +4,22 @@
// found in the LICENSE file.
//
// VaryingPacking:
// Class which describes a mapping from varyings to registers in D3D
// for linking between shader stages.
// Class which describes a mapping from varyings to registers, according
// to the spec, or using custom packing algorithms. We also keep a register
// allocation list for the D3D renderer.
//
#include "libANGLE/renderer/d3d/hlsl/VaryingPacking.h"
#include "libANGLE/VaryingPacking.h"
#include "common/utilities.h"
#include "compiler/translator/blocklayoutHLSL.h"
#include "libANGLE/Program.h"
namespace rx
namespace gl
{
// Implementation of VaryingPacking::BuiltinVarying
VaryingPacking::BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false)
{
}
std::string VaryingPacking::BuiltinVarying::str() const
{
return (systemValue ? semantic : (semantic + Str(index)));
}
void VaryingPacking::BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
{
enabled = true;
semantic = systemValueSemantic;
systemValue = true;
}
void VaryingPacking::BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
{
enabled = true;
semantic = semanticVal;
index = indexVal;
}
// Implementation of VaryingPacking
VaryingPacking::VaryingPacking(GLuint maxVaryingVectors)
: mRegisterMap(maxVaryingVectors), mBuiltinInfo(SHADER_TYPE_MAX)
VaryingPacking::VaryingPacking(GLuint maxVaryingVectors, PackMode packMode)
: mRegisterMap(maxVaryingVectors), mPackMode(packMode)
{
}
......@@ -56,7 +32,7 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
const auto &varying = *packedVarying.varying;
// "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."
// where N is the greater of C and R."
// 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.
ASSERT(!varying.isStruct());
......@@ -64,6 +40,13 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
unsigned int varyingRows = gl::VariableRowCount(transposedType);
unsigned int varyingColumns = gl::VariableColumnCount(transposedType);
// "Variables of type mat2 occupies 2 complete rows."
// For non-WebGL contexts, we allow mat2 to occupy only two columns per row.
if (mPackMode == PackMode::WEBGL_STRICT && varying.type == GL_FLOAT_MAT2)
{
varyingColumns = 4;
}
// "Arrays of size N are assumed to take N times the size of the base type"
varyingRows *= varying.elementCount();
......@@ -161,7 +144,12 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
registerInfo.registerColumn = bestColumn;
registerInfo.varyingArrayIndex = arrayIndex;
registerInfo.varyingRowIndex = 0;
mRegisterList.push_back(registerInfo);
// Do not record register info for builtins.
// TODO(jmadill): Clean this up.
if (!packedVarying.varying->isBuiltIn())
{
mRegisterList.push_back(registerInfo);
}
mRegisterMap[row + arrayIndex][bestColumn] = true;
}
break;
......@@ -218,7 +206,12 @@ void VaryingPacking::insert(unsigned int registerRow,
registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
registerInfo.varyingRowIndex = varyingRow;
registerInfo.varyingArrayIndex = arrayElement;
mRegisterList.push_back(registerInfo);
// Do not record register info for builtins.
// TODO(jmadill): Clean this up.
if (!packedVarying.varying->isBuiltIn())
{
mRegisterList.push_back(registerInfo);
}
for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
{
......@@ -242,7 +235,7 @@ bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
const auto &varying = *packedVarying.varying;
// Do not assign registers to built-in or unreferenced varyings
if (varying.isBuiltIn() || (!varying.staticUse && !packedVarying.isStructField()))
if (!varying.staticUse && !packedVarying.isStructField())
{
continue;
}
......@@ -315,11 +308,6 @@ bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
return true;
}
bool VaryingPacking::validateBuiltins() const
{
return (static_cast<size_t>(getRegisterCount()) <= mRegisterMap.size());
}
unsigned int VaryingPacking::getRegisterCount() const
{
unsigned int count = 0;
......@@ -332,16 +320,6 @@ unsigned int VaryingPacking::getRegisterCount() const
}
}
if (mBuiltinInfo[SHADER_PIXEL].glFragCoord.enabled)
{
++count;
}
if (mBuiltinInfo[SHADER_PIXEL].glPointCoord.enabled)
{
++count;
}
return count;
}
......
......@@ -4,26 +4,23 @@
// found in the LICENSE file.
//
// VaryingPacking:
// Class which describes a mapping from varyings to registers in D3D
// for linking between shader stages.
// Class which describes a mapping from varyings to registers, according
// to the spec, or using custom packing algorithms. We also keep a register
// allocation list for the D3D renderer.
//
#ifndef LIBANGLE_RENDERER_D3D_HLSL_VARYINGPACKING_H_
#define LIBANGLE_RENDERER_D3D_HLSL_VARYINGPACKING_H_
#ifndef LIBANGLE_VARYINGPACKING_H_
#define LIBANGLE_VARYINGPACKING_H_
#include <GLSLANG/ShaderVars.h>
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/renderer/d3d/hlsl/hlsl_utils.h"
namespace gl
{
class InfoLog;
}
namespace rx
{
struct PackedVarying
{
PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
......@@ -103,19 +100,25 @@ struct PackedVaryingRegister final
std::string structFieldName;
};
// Supported packing modes:
enum class PackMode
{
// We treat mat2 arrays as taking two full rows.
WEBGL_STRICT,
// We allow mat2 to take a 2x2 chunk.
ANGLE_RELAXED,
};
class VaryingPacking final : angle::NonCopyable
{
public:
VaryingPacking(GLuint maxVaryingVectors);
VaryingPacking(GLuint maxVaryingVectors, PackMode packMode);
bool packUserVaryings(gl::InfoLog &infoLog,
const std::vector<PackedVarying> &packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings);
// Some built-in varyings require emulation that eats up available registers. This method
// checks that we're within the register limits of the implementation.
bool validateBuiltins() const;
struct Register
{
Register() { data[0] = data[1] = data[2] = data[3] = false; }
......@@ -135,34 +138,7 @@ class VaryingPacking final : angle::NonCopyable
return static_cast<unsigned int>(mRegisterList.size());
}
unsigned int getRegisterCount() const;
struct BuiltinVarying final : angle::NonCopyable
{
BuiltinVarying();
std::string str() const;
void enableSystem(const std::string &systemValueSemantic);
void enable(const std::string &semanticVal, unsigned int indexVal);
bool enabled;
std::string semantic;
unsigned int index;
bool systemValue;
};
struct BuiltinInfo
{
BuiltinVarying dxPosition;
BuiltinVarying glPosition;
BuiltinVarying glFragCoord;
BuiltinVarying glPointCoord;
BuiltinVarying glPointSize;
};
const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
BuiltinInfo &builtins(ShaderType shaderType) { return mBuiltinInfo[shaderType]; }
bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; }
size_t getRegisterMapSize() const { return mRegisterMap.size(); }
private:
bool packVarying(const PackedVarying &packedVarying);
......@@ -177,9 +153,9 @@ class VaryingPacking final : angle::NonCopyable
std::vector<Register> mRegisterMap;
std::vector<PackedVaryingRegister> mRegisterList;
std::vector<BuiltinInfo> mBuiltinInfo;
PackMode mPackMode;
};
} // namespace rx
} // namespace gl
#endif // LIBANGLE_RENDERER_D3D_HLSL_VARYINGPACKING_H_
#endif // LIBANGLE_VARYINGPACKING_H_
......@@ -7,12 +7,14 @@
// Tests for ANGLE's internal varying packing algorithm.
//
#include "libANGLE/renderer/d3d/hlsl/VaryingPacking.h"
#include "libANGLE/VaryingPacking.h"
#include <gtest/gtest.h>
#include "libANGLE/Program.h"
using namespace gl;
namespace
{
......@@ -22,26 +24,31 @@ class VaryingPackingTest : public ::testing::TestWithParam<GLuint>
VaryingPackingTest() {}
bool testVaryingPacking(const std::vector<sh::Varying> &shVaryings,
rx::VaryingPacking *varyingPacking)
VaryingPacking *varyingPacking)
{
std::vector<rx::PackedVarying> packedVaryings;
std::vector<PackedVarying> packedVaryings;
for (const auto &shVarying : shVaryings)
{
packedVaryings.push_back(rx::PackedVarying(shVarying, shVarying.interpolation));
packedVaryings.push_back(PackedVarying(shVarying, shVarying.interpolation));
}
gl::InfoLog infoLog;
InfoLog infoLog;
std::vector<std::string> transformFeedbackVaryings;
if (!varyingPacking->packUserVaryings(infoLog, packedVaryings, transformFeedbackVaryings))
return false;
return varyingPacking->validateBuiltins();
return varyingPacking->packUserVaryings(infoLog, packedVaryings, transformFeedbackVaryings);
}
// Uses the "relaxed" ANGLE packing mode.
bool packVaryings(GLuint maxVaryings, const std::vector<sh::Varying> &shVaryings)
{
rx::VaryingPacking varyingPacking(maxVaryings);
VaryingPacking varyingPacking(maxVaryings, PackMode::ANGLE_RELAXED);
return testVaryingPacking(shVaryings, &varyingPacking);
}
// Uses the stricter WebGL style packing rules.
bool packVaryingsStrict(GLuint maxVaryings, const std::vector<sh::Varying> &shVaryings)
{
VaryingPacking varyingPacking(maxVaryings, PackMode::WEBGL_STRICT);
return testVaryingPacking(shVaryings, &varyingPacking);
}
......@@ -85,38 +92,6 @@ TEST_P(VaryingPackingTest, OneVaryingLargerThanMax)
ASSERT_FALSE(packVaryings(1, MakeVaryings(GL_FLOAT_MAT4, 1, 0)));
}
// Tests that using FragCoord as a user varying will eat up a register.
TEST_P(VaryingPackingTest, MaxVaryingVec4PlusFragCoord)
{
const std::string &userSemantic = rx::GetVaryingSemantic(4, false);
rx::VaryingPacking varyingPacking(kMaxVaryings);
unsigned int reservedSemanticIndex = varyingPacking.getMaxSemanticIndex();
varyingPacking.builtins(rx::SHADER_PIXEL)
.glFragCoord.enable(userSemantic, reservedSemanticIndex);
const auto &varyings = MakeVaryings(GL_FLOAT_VEC4, kMaxVaryings, 0);
ASSERT_FALSE(testVaryingPacking(varyings, &varyingPacking));
}
// Tests that using PointCoord as a user varying will eat up a register.
TEST_P(VaryingPackingTest, MaxVaryingVec4PlusPointCoord)
{
const std::string &userSemantic = rx::GetVaryingSemantic(4, false);
rx::VaryingPacking varyingPacking(kMaxVaryings);
unsigned int reservedSemanticIndex = varyingPacking.getMaxSemanticIndex();
varyingPacking.builtins(rx::SHADER_PIXEL)
.glPointCoord.enable(userSemantic, reservedSemanticIndex);
const auto &varyings = MakeVaryings(GL_FLOAT_VEC4, kMaxVaryings, 0);
ASSERT_FALSE(testVaryingPacking(varyings, &varyingPacking));
}
// This will overflow the available varying space.
TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3)
{
......@@ -172,6 +147,13 @@ TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
}
// WebGL should fail to pack max+1 vec2 arrays, unlike our more relaxed packing.
TEST_P(VaryingPackingTest, MaxPlusOneMat2VaryingsFailsWebGL)
{
auto varyings = MakeVaryings(GL_FLOAT_MAT2, kMaxVaryings / 2 + 1, 0);
ASSERT_FALSE(packVaryingsStrict(kMaxVaryings, varyings));
}
// Makes separate tests for different values of kMaxVaryings.
INSTANTIATE_TEST_CASE_P(, VaryingPackingTest, ::testing::Values(1, 4, 8));
......
......@@ -17,6 +17,11 @@
#include <map>
namespace gl
{
class VaryingPacking;
}
namespace sh
{
struct BlockMemberInfo;
......@@ -40,7 +45,9 @@ class ProgramImpl : angle::NonCopyable
virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
virtual void setBinaryRetrievableHint(bool retrievable) = 0;
virtual LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) = 0;
virtual LinkResult link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog) = 0;
virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;
......
......@@ -27,7 +27,8 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
MOCK_METHOD2(link, LinkResult(const gl::ContextState &, gl::InfoLog &));
MOCK_METHOD3(link,
LinkResult(const gl::ContextState &, const gl::VaryingPacking &, gl::InfoLog &));
MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
MOCK_METHOD3(setUniform1fv, void(GLint, GLsizei, const GLfloat *));
......
......@@ -29,15 +29,14 @@ namespace gl
{
class InfoLog;
struct VariableLocation;
class VaryingPacking;
struct VertexAttribute;
}
namespace rx
{
struct PackedVarying;
class ProgramD3DMetadata;
class ShaderD3D;
class VaryingPacking;
struct PixelShaderOutputVariable
{
......@@ -47,6 +46,54 @@ struct PixelShaderOutputVariable
size_t outputIndex;
};
struct BuiltinVarying final : angle::NonCopyable
{
BuiltinVarying();
std::string str() const;
void enableSystem(const std::string &systemValueSemantic);
void enable(const std::string &semanticVal, unsigned int indexVal);
bool enabled;
std::string semantic;
unsigned int index;
bool systemValue;
};
struct BuiltinInfo
{
BuiltinVarying dxPosition;
BuiltinVarying glPosition;
BuiltinVarying glFragCoord;
BuiltinVarying glPointCoord;
BuiltinVarying glPointSize;
};
inline std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
{
// SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
// In D3D11 we manually compute gl_PointCoord in the GS.
return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
}
class BuiltinVaryingsD3D
{
public:
BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata, const gl::VaryingPacking &packing);
bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; }
const BuiltinInfo &operator[](ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
BuiltinInfo &operator[](ShaderType shaderType) { return mBuiltinInfo[shaderType]; }
private:
void updateBuiltins(ShaderType shaderType,
const ProgramD3DMetadata &metadata,
const gl::VaryingPacking &packing);
std::array<BuiltinInfo, SHADER_TYPE_MAX> mBuiltinInfo;
};
class DynamicHLSL : angle::NonCopyable
{
public:
......@@ -61,14 +108,16 @@ class DynamicHLSL : angle::NonCopyable
const std::vector<PixelShaderOutputVariable> &outputVariables,
bool usesFragDepth,
const std::vector<GLenum> &outputLayout) const;
bool generateShaderLinkHLSL(const gl::ContextState &data,
void generateShaderLinkHLSL(const gl::ContextState &data,
const gl::ProgramState &programData,
const ProgramD3DMetadata &programMetadata,
const VaryingPacking &varyingPacking,
const gl::VaryingPacking &varyingPacking,
const BuiltinVaryingsD3D &builtinsD3D,
std::string *pixelHLSL,
std::string *vertexHLSL) const;
std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const;
std::string generateGeometryShaderPreamble(const gl::VaryingPacking &varyingPacking,
const BuiltinVaryingsD3D &builtinsD3D) const;
std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::ContextState &data,
......@@ -84,11 +133,10 @@ class DynamicHLSL : angle::NonCopyable
private:
RendererD3D *const mRenderer;
void generateVaryingLinkHLSL(ShaderType shaderType,
const VaryingPacking &varyingPacking,
std::stringstream &linkStream) const;
void generateVaryingHLSL(const VaryingPacking &varyingPacking,
std::stringstream &hlslStream) const;
void generateVaryingLinkHLSL(const gl::VaryingPacking &varyingPacking,
const BuiltinInfo &builtins,
bool programUsesPointSize,
std::stringstream &hlslStream) const;
// Prepend an underscore
static std::string decorateVariable(const std::string &name);
......@@ -97,6 +145,6 @@ class DynamicHLSL : angle::NonCopyable
const sh::ShaderVariable &shaderAttrib) const;
};
}
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
......@@ -119,9 +119,6 @@ class ProgramD3DMetadata final : angle::NonCopyable
GLint getMajorShaderVersion() const;
const ShaderD3D *getFragmentShader() const;
// Applies the metadata structure to the varying packing.
void updatePackingBuiltins(ShaderType shaderType, VaryingPacking *packing);
private:
const int mRendererMajorShaderModel;
const std::string mShaderModelSuffix;
......@@ -170,7 +167,9 @@ class ProgramD3D : public ProgramImpl
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog);
LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
LinkResult link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
......@@ -354,7 +353,8 @@ class ProgramD3D : public ProgramImpl
LinkResult compileProgramExecutables(const gl::ContextState &data, gl::InfoLog &infoLog);
void gatherTransformFeedbackVaryings(const VaryingPacking &varyings);
void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings,
const BuiltinInfo &builtins);
D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location);
......
......@@ -17,7 +17,6 @@
#include "libANGLE/Device.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/hlsl/hlsl_utils.h"
#include "libANGLE/renderer/d3d/formatutilsD3D.h"
#include "libANGLE/Version.h"
#include "libANGLE/WorkerThread.h"
......@@ -71,6 +70,14 @@ enum RendererClass
RENDERER_D3D9
};
enum ShaderType
{
SHADER_VERTEX,
SHADER_PIXEL,
SHADER_GEOMETRY,
SHADER_TYPE_MAX
};
// Useful for unit testing
class BufferFactoryD3D : angle::NonCopyable
{
......
//
// 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.
//
// hlsl_utils: Helper functions for HLSL.
#ifndef LIBANGLE_RENDERER_D3D_HLSL_HLSL_UTILS_H_
#define LIBANGLE_RENDERER_D3D_HLSL_HLSL_UTILS_H_
#include <string>
namespace rx
{
enum ShaderType
{
SHADER_VERTEX,
SHADER_PIXEL,
SHADER_GEOMETRY,
SHADER_TYPE_MAX
};
inline std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
{
// SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
// In D3D11 we manually compute gl_PointCoord in the GS.
return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
}
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_HLSL_HLSL_UTILS_H_
......@@ -111,7 +111,9 @@ void ProgramGL::setBinaryRetrievableHint(bool retrievable)
}
}
LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
LinkResult ProgramGL::link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog)
{
preLink();
......
......@@ -43,7 +43,9 @@ class ProgramGL : public ProgramImpl
gl::Error save(gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
LinkResult link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
......
......@@ -38,7 +38,9 @@ void ProgramNULL::setBinaryRetrievableHint(bool retrievable)
{
}
LinkResult ProgramNULL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
LinkResult ProgramNULL::link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog)
{
return true;
}
......
......@@ -27,7 +27,9 @@ class ProgramNULL : public ProgramImpl
gl::Error save(gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
LinkResult link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
......
......@@ -41,7 +41,9 @@ void ProgramVk::setBinaryRetrievableHint(bool retrievable)
UNIMPLEMENTED();
}
LinkResult ProgramVk::link(const gl::ContextState &data, gl::InfoLog &infoLog)
LinkResult ProgramVk::link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION);
......
......@@ -27,7 +27,9 @@ class ProgramVk : public ProgramImpl
gl::Error save(gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
LinkResult link(const gl::ContextState &data,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
......
......@@ -11,6 +11,7 @@
#include <gtest/gtest.h>
#include "libANGLE/ContextState.h"
#include "libANGLE/VaryingPacking.h"
#include "libANGLE/renderer/FramebufferImpl_mock.h"
#include "libANGLE/renderer/ProgramImpl_mock.h"
#include "libANGLE/renderer/TextureImpl_mock.h"
......
......@@ -146,6 +146,8 @@
'libANGLE/TransformFeedback.h',
'libANGLE/Uniform.cpp',
'libANGLE/Uniform.h',
'libANGLE/VaryingPacking.cpp',
'libANGLE/VaryingPacking.h',
'libANGLE/Version.h',
'libANGLE/Version.inl',
'libANGLE/VertexArray.cpp',
......@@ -271,12 +273,6 @@
'libANGLE/renderer/d3d/VertexDataManager.cpp',
'libANGLE/renderer/d3d/VertexDataManager.h',
],
'libangle_d3d_hlsl_sources':
[
'libANGLE/renderer/d3d/hlsl/VaryingPacking.cpp',
'libANGLE/renderer/d3d/hlsl/VaryingPacking.h',
'libANGLE/renderer/d3d/hlsl/hlsl_utils.h',
],
'libangle_d3d9_sources':
[
'libANGLE/renderer/d3d/d3d9/Blit9.cpp',
......@@ -830,7 +826,6 @@
{
'sources':
[
'<@(libangle_d3d_hlsl_sources)',
'<@(libangle_d3d_shared_sources)',
],
}],
......
......@@ -32,6 +32,7 @@
'<(angle_path)/src/libANGLE/ResourceManager_unittest.cpp',
'<(angle_path)/src/libANGLE/Surface_unittest.cpp',
'<(angle_path)/src/libANGLE/TransformFeedback_unittest.cpp',
'<(angle_path)/src/libANGLE/VaryingPacking_unittest.cpp',
'<(angle_path)/src/libANGLE/WorkerThread_unittest.cpp',
'<(angle_path)/src/libANGLE/renderer/BufferImpl_mock.h',
'<(angle_path)/src/libANGLE/renderer/FramebufferImpl_mock.h',
......@@ -103,7 +104,6 @@
# TODO(jmadill): should probably call this windows sources
'angle_unittests_hlsl_sources':
[
'<(angle_path)/src/libANGLE/renderer/d3d/VaryingPacking_unittest.cpp',
'<(angle_path)/src/tests/compiler_tests/UnrollFlatten_test.cpp',
],
},
......
......@@ -1357,7 +1357,12 @@ TEST_P(GLSLTest, MaxVaryingVec2Arrays)
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
VaryingTestBase(0, 0, 0, maxVaryings, 0, 0, 0, 0, false, false, false, true);
// Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
// we should be aware that when we're packing into an odd number of varying registers the
// last row will be empty and can not fit the final vec2 arrary.
GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
}
// Verify shader source with a fixed length that is less than the null-terminated length will compile.
......@@ -2520,6 +2525,73 @@ TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
}
class WebGLGLSLTest : public GLSLTest
{
protected:
WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
};
TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
{
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
// Generate shader code that uses gl_FragCoord, a special fragment shader variables.
// This test should fail, since we are really using (maxVaryings + 1) varyings.
VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
}
TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
{
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
// Generate shader code that uses gl_FragCoord, a special fragment shader variables.
// This test should fail, since we are really using (maxVaryings + 1) varyings.
VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
}
TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
{
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
}
TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
{
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
}
TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
{
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
}
TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
{
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
}
TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
{
GLint maxVaryings = 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
false);
}
} // anonymous namespace
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
......@@ -2534,3 +2606,5 @@ ANGLE_INSTANTIATE_TEST(GLSLTest,
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
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