translator: Fix variable collection for gl_DepthRange.

*re-land with Linux fixes, and fix for locations*

This built-in uniform wasn't being collected in VariableInfo.cpp.
Also remove the existing workaround for D3D gl_DepthRange
collection.

BUG=angleproject:991
BUG=478570

Change-Id: Iba84651bfc58f82fd4ce039421874f561f83c348
Reviewed-on: https://chromium-review.googlesource.com/268840
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Jamie Madill 2015-05-04 11:24:57 -04:00
Родитель 931c78cb7f
Коммит 55def58323
12 изменённых файлов: 238 добавлений и 35 удалений

Просмотреть файл

@ -70,6 +70,8 @@ struct COMPILER_EXPORT ShaderVariable
const ShaderVariable **leafVar,
std::string* originalFullName) const;
bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
GLenum type;
GLenum precision;
std::string name;

Просмотреть файл

@ -139,6 +139,7 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
mUniforms(uniforms),
mVaryings(varyings),
mInterfaceBlocks(interfaceBlocks),
mDepthRangeAdded(false),
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
@ -170,6 +171,56 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
{
UNREACHABLE();
}
else if (symbolName == "gl_DepthRange")
{
ASSERT(symbol->getQualifier() == EvqUniform);
if (!mDepthRangeAdded)
{
Uniform info;
const char kName[] = "gl_DepthRange";
info.name = kName;
info.mappedName = kName;
info.type = GL_STRUCT_ANGLEX;
info.arraySize = 0;
info.precision = GL_NONE;
info.staticUse = true;
ShaderVariable nearInfo;
const char kNearName[] = "near";
nearInfo.name = kNearName;
nearInfo.mappedName = kNearName;
nearInfo.type = GL_FLOAT;
nearInfo.arraySize = 0;
nearInfo.precision = GL_HIGH_FLOAT;
nearInfo.staticUse = true;
ShaderVariable farInfo;
const char kFarName[] = "far";
farInfo.name = kFarName;
farInfo.mappedName = kFarName;
farInfo.type = GL_FLOAT;
farInfo.arraySize = 0;
farInfo.precision = GL_HIGH_FLOAT;
farInfo.staticUse = true;
ShaderVariable diffInfo;
const char kDiffName[] = "diff";
diffInfo.name = kDiffName;
diffInfo.mappedName = kDiffName;
diffInfo.type = GL_FLOAT;
diffInfo.arraySize = 0;
diffInfo.precision = GL_HIGH_FLOAT;
diffInfo.staticUse = true;
info.fields.push_back(nearInfo);
info.fields.push_back(farInfo);
info.fields.push_back(diffInfo);
mUniforms->push_back(info);
mDepthRangeAdded = true;
}
}
else
{
switch (symbol->getQualifier())
@ -192,7 +243,6 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
// Set static use on the parent interface block here
namedBlock->staticUse = true;
}
else
{
@ -200,7 +250,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
}
// It's an internal error to reference an undefined user uniform
ASSERT(symbolName.compare(0, 3, "gl_") == 0 || var);
ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
}
break;
case EvqFragCoord:

Просмотреть файл

@ -47,6 +47,7 @@ class CollectVariables : public TIntermTraverser
std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
bool mDepthRangeAdded;
bool mPointCoordAdded;
bool mFrontFacingAdded;
bool mFragCoordAdded;

Просмотреть файл

@ -45,7 +45,6 @@ struct PackedVarying : public sh::Varying
{}
bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
void resetRegisterAssignment()
{

Просмотреть файл

@ -80,6 +80,11 @@ bool LinkedUniform::isSampler() const
return IsSamplerType(type);
}
bool LinkedUniform::isBuiltIn() const
{
return name.compare(0, 3, "gl_") == 0;
}
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
: name(name),
elementIndex(elementIndex),

Просмотреть файл

@ -32,6 +32,7 @@ struct LinkedUniform : angle::NonCopyable
bool isInDefaultBlock() const;
size_t dataSize() const;
bool isSampler() const;
bool isBuiltIn() const;
const GLenum type;
const GLenum precision;

Просмотреть файл

@ -1375,7 +1375,9 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad
if (uniform.staticUse)
{
defineUniformBase(vertexShaderD3D, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
unsigned int registerBase = uniform.isBuiltIn() ? GL_INVALID_INDEX :
vertexShaderD3D->getUniformRegister(uniform.name);
defineUniformBase(vertexShaderD3D, uniform, registerBase);
}
}
@ -1385,7 +1387,9 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad
if (uniform.staticUse)
{
defineUniformBase(fragmentShaderD3D, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
unsigned int registerBase = uniform.isBuiltIn() ? GL_INVALID_INDEX :
fragmentShaderD3D->getUniformRegister(uniform.name);
defineUniformBase(fragmentShaderD3D, uniform, registerBase);
}
}
@ -1396,21 +1400,17 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad
initializeUniformStorage();
// special case for gl_DepthRange, the only built-in uniform (also a struct)
if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange())
{
const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo();
mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo));
mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo));
mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo));
}
return true;
}
void ProgramD3D::defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister)
{
if (uniformRegister == GL_INVALID_INDEX)
{
defineUniform(shader, uniform, uniform.name, nullptr);
return;
}
ShShaderOutput outputType = shader->getCompilerOutputType();
sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
encoder.skipRegisters(uniformRegister);
@ -1427,7 +1427,8 @@ void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable
{
const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
encoder->enterAggregateType();
if (encoder)
encoder->enterAggregateType();
for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
{
@ -1437,13 +1438,14 @@ void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable
defineUniform(shader, field, fieldFullName, encoder);
}
encoder->exitAggregateType();
if (encoder)
encoder->exitAggregateType();
}
}
else // Not a struct
{
// Arrays are treated as aggregate types
if (uniform.isArray())
if (uniform.isArray() && encoder)
{
encoder->enterAggregateType();
}
@ -1451,29 +1453,36 @@ void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable
gl::LinkedUniform *linkedUniform = getUniformByName(fullName);
// Advance the uniform offset, to track registers allocation for structs
sh::BlockMemberInfo blockInfo = encoder->encodeType(uniform.type, uniform.arraySize, false);
sh::BlockMemberInfo blockInfo = encoder ?
encoder->encodeType(uniform.type, uniform.arraySize, false) :
sh::BlockMemberInfo::getDefaultBlockInfo();
if (!linkedUniform)
{
linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
-1, sh::BlockMemberInfo::getDefaultBlockInfo());
ASSERT(linkedUniform);
linkedUniform->registerElement = sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo);
if (encoder)
linkedUniform->registerElement = sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo);
mUniforms.push_back(linkedUniform);
}
if (shader->getShaderType() == GL_FRAGMENT_SHADER)
if (encoder)
{
linkedUniform->psRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo);
if (shader->getShaderType() == GL_FRAGMENT_SHADER)
{
linkedUniform->psRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo);
}
else if (shader->getShaderType() == GL_VERTEX_SHADER)
{
linkedUniform->vsRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo);
}
else UNREACHABLE();
}
else if (shader->getShaderType() == GL_VERTEX_SHADER)
{
linkedUniform->vsRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo);
}
else UNREACHABLE();
// Arrays are treated as aggregate types
if (uniform.isArray())
if (uniform.isArray() && encoder)
{
encoder->exitAggregateType();
}
@ -1934,9 +1943,12 @@ bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
}
}
for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
{
mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
if (!uniform.isBuiltIn())
{
mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayIndex, uniformIndex));
}
}
}

Просмотреть файл

@ -218,7 +218,7 @@ void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source)
{
const sh::Uniform &uniform = mUniforms[uniformIndex];
if (uniform.staticUse)
if (uniform.staticUse && !uniform.isBuiltIn())
{
unsigned int index = static_cast<unsigned int>(-1);
bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index);

Просмотреть файл

@ -61,6 +61,7 @@
},
'dependencies':
[
'<(angle_path)/src/angle.gyp:libANGLE',
'<(angle_path)/src/angle.gyp:libEGL',
'<(angle_path)/src/angle.gyp:libGLESv2',
'<(angle_path)/src/tests/tests.gyp:angle_test_support',

Просмотреть файл

@ -19,8 +19,10 @@ class CollectVariablesTest : public testing::Test
{
public:
CollectVariablesTest(GLenum shaderType)
: mShaderType(shaderType)
{}
: mShaderType(shaderType),
mTranslator(nullptr)
{
}
protected:
virtual void SetUp()
@ -29,14 +31,67 @@ class CollectVariablesTest : public testing::Test
ShInitBuiltInResources(&resources);
resources.MaxDrawBuffers = 8;
initTranslator(resources);
}
virtual void TearDown()
{
SafeDelete(mTranslator);
}
void initTranslator(const ShBuiltInResources &resources)
{
SafeDelete(mTranslator);
mTranslator = new TranslatorGLSL(
mShaderType, SH_GLES3_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT);
ASSERT_TRUE(mTranslator->Init(resources));
}
virtual void TearDown()
// For use in the gl_DepthRange tests.
void validateDepthRangeShader(const std::string &shaderString)
{
delete mTranslator;
const char *shaderStrings[] = { shaderString.c_str() };
ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES));
const std::vector<sh::Uniform> &uniforms = mTranslator->getUniforms();
ASSERT_EQ(1u, uniforms.size());
const sh::Uniform &uniform = uniforms[0];
EXPECT_EQ("gl_DepthRange", uniform.name);
ASSERT_TRUE(uniform.isStruct());
ASSERT_EQ(3u, uniform.fields.size());
bool foundNear = false;
bool foundFar = false;
bool foundDiff = false;
for (const auto &field : uniform.fields)
{
if (field.name == "near")
{
EXPECT_FALSE(foundNear);
foundNear = true;
}
else if (field.name == "far")
{
EXPECT_FALSE(foundFar);
foundFar = true;
}
else
{
ASSERT_EQ("diff", field.name);
EXPECT_FALSE(foundDiff);
foundDiff = true;
}
EXPECT_EQ(0u, field.arraySize);
EXPECT_FALSE(field.isStruct());
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
EXPECT_TRUE(field.staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
}
EXPECT_TRUE(foundNear && foundFar && foundDiff);
}
GLenum mShaderType;
@ -369,3 +424,27 @@ TEST_F(CollectVertexVariablesTest, VaryingInterpolation)
EXPECT_EQ("vary", varying->name);
EXPECT_EQ(sh::INTERPOLATION_CENTROID, varying->interpolation);
}
// Test for builtin uniform "gl_DepthRange" (Vertex shader)
TEST_F(CollectVertexVariablesTest, DepthRange)
{
const std::string &shaderString =
"attribute vec4 position;\n"
"void main() {\n"
" gl_Position = position + vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1.0);\n"
"}\n";
validateDepthRangeShader(shaderString);
}
// Test for builtin uniform "gl_DepthRange" (Fragment shader)
TEST_F(CollectFragmentVariablesTest, DepthRange)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main() {\n"
" gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1.0);\n"
"}\n";
validateDepthRangeShader(shaderString);
}

Просмотреть файл

@ -1,5 +1,14 @@
//
// 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.
//
#include "ANGLETest.h"
#include "libANGLE/Context.h"
#include "libANGLE/Program.h"
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_TYPED_TEST_CASE(GLSLTest, ES2_D3D9, ES2_D3D11);
@ -1067,3 +1076,36 @@ TYPED_TEST(GLSLTest, StructSpecifiersUniforms)
GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
EXPECT_NE(0u, program);
}
// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
// beginning with "gl_" are filtered out by our validation logic, we must
// bypass the validation to test the behaviour of the implementation.
// (note this test is still Impl-independent)
TYPED_TEST(GLSLTest, DepthRangeUniforms)
{
const std::string fragmentShaderSource = SHADER_SOURCE
(
precision mediump float;
void main()
{
gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
}
);
GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
EXPECT_NE(0u, program);
// dive into the ANGLE internals, so we can bypass validation.
gl::Context *context = reinterpret_cast<gl::Context *>(getEGLWindow()->getContext());
gl::Program *glProgram = context->getProgram(program);
GLint nearIndex = glProgram->getUniformLocation("gl_DepthRange.near");
EXPECT_EQ(-1, nearIndex);
// Test drawing does not throw an exception.
drawQuad(program, "inputAttribute", 0.5f);
EXPECT_GL_NO_ERROR();
glDeleteProgram(program);
}

Просмотреть файл

@ -1,5 +1,16 @@
//
// 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.
//
#ifndef ANGLE_ENABLE_D3D9
#define ANGLE_ENABLE_D3D9
#endif
#ifndef ANGLE_ENABLE_D3D11
#define ANGLE_ENABLE_D3D11
#endif
#include "ANGLETest.h"
#include "com_utils.h"