зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
931c78cb7f
Коммит
55def58323
|
@ -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"
|
||||
|
|
Загрузка…
Ссылка в новой задаче