Commit 78d35692 by Jamie Madill

Re^5-land "Move Uniform and UBO info to the gl::Program layer."

This data was previously stored entirely in the Impl level. Move as much as possible to the GL level, using a read-only view in the Impl level. Some information in D3D-specific, and should be stored separately in the Impl. This patch has a lot of refactoring that splits the D3D and GL info, and moves as much validation as possible to the GL layer, where it is shared between the back-ends. Re-land with fix for dEQP unused uniforms. The fix involves storing a local copy of all uniform data in the GL layer. This will also let us validate sampler indexes during draw calls at the GL layer. Re-re-land with a fix for multiply defined symbols on Clang. Re-re-re-land with a fix for boolean uniforms and Uniform{1234}f. Re^4-land with a fix for boolean uniform arrays and UBO uniforms. Re^5-land with a fix for a test warning on Linux. BUG=angleproject:1123 TEST=end2end_tests, bots, dEQP GLES3.ubo and GLES2.uniform_api Change-Id: I03afcd446d9e74573c4d4c712ed7407b91d8001c Reviewed-on: https://chromium-review.googlesource.com/299180Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent a2eb02c9
......@@ -69,13 +69,13 @@ inline int clampToInt(unsigned int x)
template <typename DestT, typename SrcT>
inline DestT clampCast(SrcT value)
{
// This assumes SrcT can properly represent DestT::min/max
// Unfortunately we can't use META_ASSERT without C++11 constexpr support
ASSERT(static_cast<DestT>(static_cast<SrcT>(std::numeric_limits<DestT>::min())) == std::numeric_limits<DestT>::min());
ASSERT(static_cast<DestT>(static_cast<SrcT>(std::numeric_limits<DestT>::max())) == std::numeric_limits<DestT>::max());
SrcT lo = static_cast<SrcT>(std::numeric_limits<DestT>::min());
SrcT hi = static_cast<SrcT>(std::numeric_limits<DestT>::max());
// This assumes SrcT can properly represent DestT::min/max. Checking this is a bit tricky,
// especially given floating point representations.
ASSERT(lo < hi);
return static_cast<DestT>(value > lo ? (value > hi ? hi : value) : lo);
}
......
......@@ -26,6 +26,8 @@ struct InterfaceBlock;
struct COMPILER_EXPORT BlockMemberInfo
{
BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
: offset(offset),
arrayStride(arrayStride),
......
......@@ -189,6 +189,16 @@ class Program : angle::NonCopyable
{
return mOutputVariables;
}
const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
const std::vector<VariableLocation> &getUniformLocations() const
{
return mUniformLocations;
}
const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; }
const LinkedUniform *getUniformByName(const std::string &name) const;
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
private:
friend class Program;
......@@ -205,10 +215,12 @@ class Program : angle::NonCopyable
std::vector<sh::Attribute> mAttributes;
std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
std::vector<LinkedUniform> mUniforms;
std::vector<VariableLocation> mUniformLocations;
std::vector<UniformBlock> mUniformBlocks;
// TODO(jmadill): use unordered/hash map when available
std::map<int, VariableLocation> mOutputVariables;
// TODO(jmadill): move more state into Data.
};
Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
......@@ -251,11 +263,10 @@ class Program : angle::NonCopyable
GLint getActiveUniformMaxLength();
GLint getActiveUniformi(GLuint index, GLenum pname) const;
bool isValidUniformLocation(GLint location) const;
LinkedUniform *getUniformByLocation(GLint location) const;
LinkedUniform *getUniformByName(const std::string &name) const;
const LinkedUniform &getUniformByLocation(GLint location) const;
GLint getUniformLocation(const std::string &name);
GLuint getUniformIndex(const std::string &name);
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
......@@ -292,7 +303,7 @@ class Program : angle::NonCopyable
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
const UniformBlock *getUniformBlockByIndex(GLuint index) const;
const UniformBlock &getUniformBlockByIndex(GLuint index) const;
void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
......@@ -330,7 +341,8 @@ class Program : angle::NonCopyable
static bool linkVaryings(InfoLog &infoLog,
const Shader *vertexShader,
const Shader *fragmentShader);
bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) const;
bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
void indexUniforms();
bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
const sh::InterfaceBlock &fragmentInterfaceBlock);
......@@ -352,6 +364,40 @@ class Program : angle::NonCopyable
std::vector<const sh::Varying *> getMergedVaryings() const;
void linkOutputVariables();
bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
struct VectorAndSamplerCount
{
VectorAndSamplerCount() : vectorCount(0), samplerCount(0) {}
VectorAndSamplerCount(const VectorAndSamplerCount &other) = default;
VectorAndSamplerCount &operator=(const VectorAndSamplerCount &other) = default;
VectorAndSamplerCount &operator+=(const VectorAndSamplerCount &other)
{
vectorCount += other.vectorCount;
samplerCount += other.samplerCount;
return *this;
}
unsigned int vectorCount;
unsigned int samplerCount;
};
VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
const std::string &fullName);
void gatherInterfaceBlockInfo();
void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
template <typename T>
void setUniformInternal(GLint location, GLsizei count, const T *v);
template <size_t cols, size_t rows, typename T>
void setMatrixUniformInternal(GLint location, GLsizei count, GLboolean transpose, const T *v);
template <typename DestT>
void getUniformInternal(GLint location, DestT *dataOut) const;
Data mData;
rx::ProgramImpl *mProgram;
......
......@@ -13,55 +13,51 @@
namespace gl
{
LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize,
const int blockIndex, const sh::BlockMemberInfo &blockInfo)
: type(type),
precision(precision),
name(name),
arraySize(arraySize),
blockIndex(blockIndex),
blockInfo(blockInfo),
data(NULL),
dirty(true),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX),
registerCount(0),
registerElement(0)
LinkedUniform::LinkedUniform()
: blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
{
// We use data storage for default block uniforms to cache values that are sent to D3D during rendering
// Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
if (isInDefaultBlock())
{
size_t bytes = dataSize();
data = new unsigned char[bytes];
memset(data, 0, bytes);
registerCount = VariableRowCount(type) * elementCount();
}
}
LinkedUniform::~LinkedUniform()
LinkedUniform::LinkedUniform(GLenum typeIn,
GLenum precisionIn,
const std::string &nameIn,
unsigned int arraySizeIn,
const int blockIndexIn,
const sh::BlockMemberInfo &blockInfoIn)
: blockIndex(blockIndexIn), blockInfo(blockInfoIn)
{
delete[] data;
type = typeIn;
precision = precisionIn;
name = nameIn;
arraySize = arraySizeIn;
}
bool LinkedUniform::isArray() const
LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
: sh::Uniform(uniform), blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
{
return arraySize > 0;
}
unsigned int LinkedUniform::elementCount() const
LinkedUniform::LinkedUniform(const LinkedUniform &uniform)
: sh::Uniform(uniform), blockIndex(uniform.blockIndex), blockInfo(uniform.blockInfo)
{
return arraySize > 0 ? arraySize : 1;
// This function is not intended to be called during runtime.
ASSERT(uniform.mLazyData.empty());
}
bool LinkedUniform::isReferencedByVertexShader() const
LinkedUniform &LinkedUniform::operator=(const LinkedUniform &uniform)
{
return vsRegisterIndex != GL_INVALID_INDEX;
// This function is not intended to be called during runtime.
ASSERT(uniform.mLazyData.empty());
sh::Uniform::operator=(uniform);
blockIndex = uniform.blockIndex;
blockInfo = uniform.blockInfo;
return *this;
}
bool LinkedUniform::isReferencedByFragmentShader() const
LinkedUniform::~LinkedUniform()
{
return psRegisterIndex != GL_INVALID_INDEX;
}
bool LinkedUniform::isInDefaultBlock() const
......@@ -72,7 +68,30 @@ bool LinkedUniform::isInDefaultBlock() const
size_t LinkedUniform::dataSize() const
{
ASSERT(type != GL_STRUCT_ANGLEX);
return VariableInternalSize(type) * elementCount();
if (mLazyData.empty())
{
mLazyData.resize(VariableExternalSize(type) * elementCount());
ASSERT(!mLazyData.empty());
}
return mLazyData.size();
}
uint8_t *LinkedUniform::data()
{
if (mLazyData.empty())
{
// dataSize() will init the data store.
size_t size = dataSize();
memset(mLazyData.data(), 0, size);
}
return mLazyData.data();
}
const uint8_t *LinkedUniform::data() const
{
return const_cast<LinkedUniform *>(this)->data();
}
bool LinkedUniform::isSampler() const
......@@ -80,33 +99,48 @@ bool LinkedUniform::isSampler() const
return IsSamplerType(type);
}
bool LinkedUniform::isBuiltIn() const
bool LinkedUniform::isField() const
{
return name.compare(0, 3, "gl_") == 0;
return name.find('.') != std::string::npos;
}
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
: name(name),
elementIndex(elementIndex),
dataSize(dataSize),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
size_t LinkedUniform::getElementSize() const
{
return VariableExternalSize(type);
}
bool UniformBlock::isArrayElement() const
uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex)
{
return elementIndex != GL_INVALID_INDEX;
ASSERT((!isArray() && elementIndex == 0) || (isArray() && elementIndex < arraySize));
return data() + getElementSize() * elementIndex;
}
bool UniformBlock::isReferencedByVertexShader() const
const uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) const
{
return vsRegisterIndex != GL_INVALID_INDEX;
return const_cast<LinkedUniform *>(this)->getDataPtrToElement(elementIndex);
}
bool UniformBlock::isReferencedByFragmentShader() const
UniformBlock::UniformBlock()
: isArray(false),
arrayElement(0),
dataSize(0),
vertexStaticUse(false),
fragmentStaticUse(false),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
{
}
UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn)
: name(nameIn),
isArray(isArrayIn),
arrayElement(arrayElementIn),
dataSize(0),
vertexStaticUse(false),
fragmentStaticUse(false),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
{
return psRegisterIndex != GL_INVALID_INDEX;
}
}
......@@ -12,6 +12,7 @@
#include "angle_gl.h"
#include "common/debug.h"
#include "common/MemoryBuffer.h"
#include "compiler/translator/blocklayout.h"
#include "libANGLE/angletypes.h"
......@@ -19,53 +20,47 @@ namespace gl
{
// Helper struct representing a single shader uniform
struct LinkedUniform : angle::NonCopyable
struct LinkedUniform : public sh::Uniform
{
LinkedUniform();
LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo);
LinkedUniform(const sh::Uniform &uniform);
LinkedUniform(const LinkedUniform &uniform);
LinkedUniform &operator=(const LinkedUniform &uniform);
~LinkedUniform();
bool isArray() const;
unsigned int elementCount() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
bool isInDefaultBlock() const;
size_t dataSize() const;
uint8_t *data();
const uint8_t *data() const;
bool isSampler() const;
bool isBuiltIn() const;
const GLenum type;
const GLenum precision;
const std::string name;
const unsigned int arraySize;
const int blockIndex;
const sh::BlockMemberInfo blockInfo;
bool isInDefaultBlock() const;
bool isField() const;
size_t getElementSize() const;
uint8_t *getDataPtrToElement(size_t elementIndex);
const uint8_t *getDataPtrToElement(size_t elementIndex) const;
unsigned char *data;
bool dirty;
int blockIndex;
sh::BlockMemberInfo blockInfo;
unsigned int psRegisterIndex;
unsigned int vsRegisterIndex;
unsigned int registerCount;
// Register "elements" are used for uniform structs in ES3, to appropriately identify single uniforms
// inside aggregate types, which are packed according C-like structure rules.
unsigned int registerElement;
private:
mutable rx::MemoryBuffer mLazyData;
};
// Helper struct representing a single shader uniform block
struct UniformBlock : angle::NonCopyable
struct UniformBlock
{
// use GL_INVALID_INDEX for non-array elements
UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize);
bool isArrayElement() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
const std::string name;
const unsigned int elementIndex;
const unsigned int dataSize;
UniformBlock();
UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn);
UniformBlock(const UniformBlock &other) = default;
UniformBlock &operator=(const UniformBlock &other) = default;
std::string name;
bool isArray;
unsigned int arrayElement;
unsigned int dataSize;
bool vertexStaticUse;
bool fragmentStaticUse;
std::vector<unsigned int> memberUniformIndexes;
......
......@@ -6,32 +6,24 @@
// queryconversions.cpp: Implementation of state query cast conversions
#include "libANGLE/queryconversions.h"
#include "libANGLE/Context.h"
#include "common/utilities.h"
namespace gl
{
// Helper class for converting a GL type to a GLenum:
// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap.
// We restrict our use to CastStateValue, where it eliminates duplicate parameters.
template <typename GLType>
struct CastStateValueEnum { static GLenum mEnumForType; };
template <> GLenum CastStateValueEnum<GLint>::mEnumForType = GL_INT;
template <> GLenum CastStateValueEnum<GLuint>::mEnumForType = GL_UNSIGNED_INT;
template <> GLenum CastStateValueEnum<GLboolean>::mEnumForType = GL_BOOL;
template <> GLenum CastStateValueEnum<GLint64>::mEnumForType = GL_INT_64_ANGLEX;
template <> GLenum CastStateValueEnum<GLfloat>::mEnumForType = GL_FLOAT;
namespace
{
static GLint64 ExpandFloatToInteger(GLfloat value)
GLint64 ExpandFloatToInteger(GLfloat value)
{
return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0);
}
template <typename QueryT>
static QueryT ClampToQueryRange(GLint64 value)
QueryT ClampToQueryRange(GLint64 value)
{
const GLint64 min = static_cast<GLint64>(std::numeric_limits<QueryT>::min());
const GLint64 max = static_cast<GLint64>(std::numeric_limits<QueryT>::max());
......@@ -41,8 +33,8 @@ static QueryT ClampToQueryRange(GLint64 value)
template <typename QueryT, typename NativeT>
QueryT CastStateValueToInt(GLenum pname, NativeT value)
{
GLenum queryType = CastStateValueEnum<QueryT>::mEnumForType;
GLenum nativeType = CastStateValueEnum<NativeT>::mEnumForType;
GLenum queryType = GLTypeToGLenum<QueryT>::value;
GLenum nativeType = GLTypeToGLenum<NativeT>::value;
if (nativeType == GL_FLOAT)
{
......@@ -72,18 +64,37 @@ QueryT CastStateValueToInt(GLenum pname, NativeT value)
template <typename QueryT, typename NativeT>
QueryT CastStateValue(GLenum pname, NativeT value)
{
GLenum queryType = CastStateValueEnum<QueryT>::mEnumForType;
GLenum queryType = GLTypeToGLenum<QueryT>::value;
switch (queryType)
{
case GL_INT: return CastStateValueToInt<QueryT, NativeT>(pname, value);
case GL_INT_64_ANGLEX: return CastStateValueToInt<QueryT, NativeT>(pname, value);
case GL_FLOAT: return static_cast<QueryT>(value);
case GL_BOOL: return static_cast<QueryT>(value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE);
default: UNREACHABLE(); return 0;
case GL_INT:
return CastStateValueToInt<QueryT, NativeT>(pname, value);
case GL_INT_64_ANGLEX:
return CastStateValueToInt<QueryT, NativeT>(pname, value);
case GL_FLOAT:
return static_cast<QueryT>(value);
case GL_BOOL:
return static_cast<QueryT>(value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE);
default:
UNREACHABLE();
return 0;
}
}
} // anonymous namespace
template <>
GLenum GLTypeToGLenum<GLint>::value = GL_INT;
template <>
GLenum GLTypeToGLenum<GLuint>::value = GL_UNSIGNED_INT;
template <>
GLenum GLTypeToGLenum<GLboolean>::value = GL_BOOL;
template <>
GLenum GLTypeToGLenum<GLint64>::value = GL_INT_64_ANGLEX;
template <>
GLenum GLTypeToGLenum<GLfloat>::value = GL_FLOAT;
template <typename QueryT>
void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
unsigned int numParams, QueryT *outParams)
......
......@@ -6,8 +6,25 @@
// queryconversions.h: Declaration of state query cast conversions
#ifndef LIBANGLE_QUERY_CONVERSIONS_H_
#define LIBANGLE_QUERY_CONVERSIONS_H_
#include "angle_gl.h"
#include "common/angleutils.h"
namespace gl
{
class Context;
// Helper class for converting a GL type to a GLenum:
// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap.
// We restrict our use to CastStateValue, where it eliminates duplicate parameters.
template <typename GLType>
struct GLTypeToGLenum
{
static GLenum value;
};
// The GL state query API types are: bool, int, uint, float, int64
template <typename QueryT>
......@@ -15,3 +32,5 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
unsigned int numParams, QueryT *outParams);
}
#endif // LIBANGLE_QUERY_CONVERSIONS_H_
//
// Copyright (c) 2014 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.
//
// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
#include "libANGLE/renderer/ProgramImpl.h"
#include "common/utilities.h"
namespace rx
{
LinkResult::LinkResult(bool linkSuccess, const gl::Error &error)
: linkSuccess(linkSuccess),
error(error)
{
}
ProgramImpl::ProgramImpl(const gl::Program::Data &data) : mData(data)
{
}
ProgramImpl::~ProgramImpl()
{
// Ensure that reset was called by the inherited class during destruction
ASSERT(mUniformIndex.size() == 0);
}
gl::LinkedUniform *ProgramImpl::getUniformByLocation(GLint location) const
{
ASSERT(location >= 0 && mUniformIndex.find(location) != mUniformIndex.end());
return mUniforms[mUniformIndex.at(location).index];
}
gl::LinkedUniform *ProgramImpl::getUniformByName(const std::string &name) const
{
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{
if (mUniforms[uniformIndex]->name == name)
{
return mUniforms[uniformIndex];
}
}
return NULL;
}
gl::UniformBlock *ProgramImpl::getUniformBlockByIndex(GLuint blockIndex) const
{
ASSERT(blockIndex < mUniformBlocks.size());
return mUniformBlocks[blockIndex];
}
GLint ProgramImpl::getUniformLocation(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
for (const auto &info : mUniformIndex)
{
GLuint location = info.first;
const gl::VariableLocation &uniform = info.second;
if (uniform.name == baseName)
{
const bool isArray = mUniforms[uniform.index]->isArray();
if ((isArray && uniform.element == subscript) ||
(subscript == GL_INVALID_INDEX))
{
return location;
}
}
}
return -1;
}
GLuint ProgramImpl::getUniformIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
// The app is not allowed to specify array indices other than 0 for arrays of basic types
if (subscript != 0 && subscript != GL_INVALID_INDEX)
{
return GL_INVALID_INDEX;
}
unsigned int numUniforms = static_cast<unsigned int>(mUniforms.size());
for (unsigned int index = 0; index < numUniforms; index++)
{
if (mUniforms[index]->name == baseName)
{
if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
{
return index;
}
}
}
return GL_INVALID_INDEX;
}
GLuint ProgramImpl::getUniformBlockIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
unsigned int numUniformBlocks = static_cast<unsigned int>(mUniformBlocks.size());
for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
{
const gl::UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
if (uniformBlock.name == baseName)
{
const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
if (subscript == uniformBlock.elementIndex || arrayElementZero)
{
return blockIndex;
}
}
}
return GL_INVALID_INDEX;
}
void ProgramImpl::reset()
{
SafeDeleteContainer(mUniforms);
mUniformIndex.clear();
SafeDeleteContainer(mUniformBlocks);
}
}
......@@ -23,16 +23,17 @@ namespace rx
struct LinkResult
{
LinkResult(bool linkSuccess, const gl::Error &error) : linkSuccess(linkSuccess), error(error) {}
bool linkSuccess;
gl::Error error;
LinkResult(bool linkSuccess, const gl::Error &error);
};
class ProgramImpl : angle::NonCopyable
{
public:
ProgramImpl(const gl::Program::Data &data);
virtual ~ProgramImpl();
ProgramImpl(const gl::Program::Data &data) : mData(data) {}
virtual ~ProgramImpl() {}
virtual int getShaderVersion() const = 0;
......@@ -65,41 +66,16 @@ class ProgramImpl : angle::NonCopyable
virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
virtual void getUniformfv(GLint location, GLfloat *params) = 0;
virtual void getUniformiv(GLint location, GLint *params) = 0;
virtual void getUniformuiv(GLint location, GLuint *params) = 0;
// TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to
// determine if they can be removed from this interface.
virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0;
const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; }
const std::map<GLuint, gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; }
const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; }
std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; }
std::map<GLuint, gl::VariableLocation> &getUniformIndices() { return mUniformIndex; }
std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; }
gl::LinkedUniform *getUniformByLocation(GLint location) const;
gl::LinkedUniform *getUniformByName(const std::string &name) const;
gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const;
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
GLuint getUniformBlockIndex(const std::string &name) const;
virtual void reset();
// Gather uniform block active uniform indices, and uniform block offset info.
virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) = 0;
protected:
const gl::Program::Data &mData;
std::vector<gl::LinkedUniform*> mUniforms;
// TODO: use a hash map
std::map<GLuint, gl::VariableLocation> mUniformIndex;
std::vector<gl::UniformBlock*> mUniformBlocks;
};
}
......
......@@ -20,13 +20,6 @@
#include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
namespace gl
{
struct LinkedUniform;
struct VariableLocation;
struct VertexFormat;
}
namespace rx
{
class RendererD3D;
......@@ -39,6 +32,43 @@ class ShaderExecutableD3D;
#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
#endif
// Helper struct representing a single shader uniform
struct D3DUniform
{
D3DUniform(GLenum typeIn,
const std::string &nameIn,
unsigned int arraySizeIn,
bool defaultBlock);
~D3DUniform();
bool isSampler() const;
unsigned int elementCount() const { return std::max(1u, arraySize); }
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
// Duplicated from the GL layer
GLenum type;
std::string name;
unsigned int arraySize;
// Pointer to a system copy of the data.
// TODO(jmadill): remove this in favor of gl::LinkedUniform::data().
uint8_t *data;
// Has the data been updated since the last sync?
bool dirty;
// Register information.
unsigned int vsRegisterIndex;
unsigned int psRegisterIndex;
unsigned int registerCount;
// Register "elements" are used for uniform structs in ES3, to appropriately identify single
// uniforms
// inside aggregate types, which are packed according C-like structure rules.
unsigned int registerElement;
};
class ProgramD3D : public ProgramImpl
{
public:
......@@ -73,13 +103,12 @@ class ProgramD3D : public ProgramImpl
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) override;
void initializeUniformStorage();
gl::Error applyUniforms();
gl::Error applyUniformBuffers(const gl::Data &data);
void assignUniformBlockRegister(gl::UniformBlock *uniformBlock,
GLenum shader,
unsigned int registerIndex,
const gl::Caps &caps);
void dirtyAllUniforms();
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
......@@ -104,15 +133,9 @@ class ProgramD3D : public ProgramImpl
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void getUniformfv(GLint location, GLfloat *params);
void getUniformiv(GLint location, GLint *params);
void getUniformuiv(GLint location, GLuint *params);
const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; }
const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
void reset();
unsigned int getSerial() const;
void sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
......@@ -175,19 +198,24 @@ class ProgramD3D : public ProgramImpl
GLenum textureType;
};
bool defineUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
void defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister);
void defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, const std::string &fullName,
sh::HLSLBlockEncoder *encoder);
bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps);
bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
std::vector<Sampler> &outSamplers, GLuint *outUsedRange);
typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap;
void assignUniformRegisters();
void assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform);
void assignUniformRegisters(const ShaderD3D *shader,
const sh::ShaderVariable &uniform,
const std::string &fullName,
sh::HLSLBlockEncoder *encoder);
void assignAllSamplerRegisters();
void assignSamplerRegisters(const D3DUniform *d3dUniform);
void defineUniformBlocks(const gl::Caps &caps);
void defineUniformBlock(const gl::Shader &shader,
const sh::InterfaceBlock &interfaceBlock,
const gl::Caps &caps);
static void AssignSamplers(unsigned int startSamplerIndex,
GLenum samplerType,
unsigned int samplerCount,
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
size_t defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, BlockInfoMap *blockInfoOut);
template <typename T>
void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
......@@ -195,23 +223,19 @@ class ProgramD3D : public ProgramImpl
template <int cols, int rows>
void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType);
template <typename T>
void getUniformv(GLint location, T *params, GLenum uniformType);
template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
bool inRowMajorLayout);
LinkResult compileProgramExecutables(gl::InfoLog &infoLog,
int registers,
const std::vector<PackedVarying> &packedVaryings);
void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location);
void initSemanticIndex();
void initAttributesByLayout();
void reset();
RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL;
......@@ -259,6 +283,7 @@ class ProgramD3D : public ProgramImpl
gl::InputLayout mCachedInputLayout;
std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
std::vector<D3DUniform *> mD3DUniforms;
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
......
......@@ -37,8 +37,10 @@ class DebugAnnotator;
namespace rx
{
struct D3DUniform;
class ImageD3D;
class IndexBuffer;
class ProgramD3D;
class RenderTargetD3D;
class ShaderExecutableD3D;
class SwapChainD3D;
......@@ -157,7 +159,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
const gl::Framebuffer *framebuffer,
bool rasterizerDiscard,
bool transformFeedbackActive) = 0;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0;
virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo) = 0;
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) = 0;
......
......@@ -2095,7 +2095,8 @@ gl::Error Renderer11::applyShaders(gl::Program *program,
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray)
gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray)
{
unsigned int totalRegisterCountVS = 0;
unsigned int totalRegisterCountPS = 0;
......@@ -2103,26 +2104,25 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
bool vertexUniformsDirty = false;
bool pixelUniformsDirty = false;
for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
for (const D3DUniform *uniform : uniformArray)
{
const gl::LinkedUniform &uniform = *uniformArray[uniformIndex];
if (uniform.isReferencedByVertexShader() && !uniform.isSampler())
if (uniform->isReferencedByVertexShader() && !uniform->isSampler())
{
totalRegisterCountVS += uniform.registerCount;
vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty);
totalRegisterCountVS += uniform->registerCount;
vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
}
if (uniform.isReferencedByFragmentShader() && !uniform.isSampler())
if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
{
totalRegisterCountPS += uniform.registerCount;
pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty);
totalRegisterCountPS += uniform->registerCount;
pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
}
}
const ProgramD3D *programD3D = GetAs<ProgramD3D>(&program);
const UniformStorage11 *vertexUniformStorage = GetAs<UniformStorage11>(&programD3D->getVertexUniformStorage());
const UniformStorage11 *fragmentUniformStorage = GetAs<UniformStorage11>(&programD3D->getFragmentUniformStorage());
const UniformStorage11 *vertexUniformStorage =
GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
const UniformStorage11 *fragmentUniformStorage =
GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage());
ASSERT(vertexUniformStorage);
ASSERT(fragmentUniformStorage);
......@@ -2150,26 +2150,26 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
mapPS = (float(*)[4])map.pData;
}
for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
for (const D3DUniform *uniform : uniformArray)
{
gl::LinkedUniform *uniform = uniformArray[uniformIndex];
if (uniform->isSampler())
continue;
if (!uniform->isSampler())
{
unsigned int componentCount = (4 - uniform->registerElement);
unsigned int componentCount = (4 - uniform->registerElement);
// we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would
// overwrite previously written regions of memory.
// we assume that uniforms from structs are arranged in struct order in our uniforms list.
// otherwise we would overwrite previously written regions of memory.
if (uniform->isReferencedByVertexShader() && mapVS)
{
memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount);
}
if (uniform->isReferencedByVertexShader() && mapVS)
{
memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data,
uniform->registerCount * sizeof(float) * componentCount);
}
if (uniform->isReferencedByFragmentShader() && mapPS)
{
memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount);
}
if (uniform->isReferencedByFragmentShader() && mapPS)
{
memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data,
uniform->registerCount * sizeof(float) * componentCount);
}
}
......@@ -2255,7 +2255,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
}
// GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
if (programD3D->usesGeometryShader())
if (programD3D.usesGeometryShader())
{
// needed for the point sprite geometry shader
if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
......
......@@ -137,7 +137,8 @@ class Renderer11 : public RendererD3D
bool rasterizerDiscard,
bool transformFeedbackActive) override;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
gl::Error applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) override;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo);
void applyTransformFeedbackBuffers(const gl::State &state) override;
......
......@@ -1910,46 +1910,45 @@ gl::Error Renderer9::applyShaders(gl::Program *program,
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray)
gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray)
{
for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
for (const D3DUniform *targetUniform : uniformArray)
{
gl::LinkedUniform *targetUniform = uniformArray[uniformIndex];
if (!targetUniform->dirty)
continue;
if (targetUniform->dirty)
{
GLfloat *f = (GLfloat*)targetUniform->data;
GLint *i = (GLint*)targetUniform->data;
GLfloat *f = (GLfloat *)targetUniform->data;
GLint *i = (GLint *)targetUniform->data;
switch (targetUniform->type)
{
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
switch (targetUniform->type)
{
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
break;
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
applyUniformnbv(targetUniform, i);
break;
case GL_FLOAT:
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4:
case GL_FLOAT:
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4:
applyUniformnfv(targetUniform, f);
break;
case GL_INT:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
case GL_INT:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
applyUniformniv(targetUniform, i);
break;
default:
default:
UNREACHABLE();
}
}
}
......@@ -1964,7 +1963,7 @@ gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector
return gl::Error(GL_NO_ERROR);
}
void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v)
void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
{
if (targetUniform->isReferencedByFragmentShader())
{
......@@ -1977,7 +1976,7 @@ void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat
}
}
void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v)
void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
{
ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
......@@ -1993,7 +1992,7 @@ void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v
applyUniformnfv(targetUniform, (GLfloat*)vector);
}
void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v)
void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
{
ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
......
......@@ -32,10 +32,12 @@ namespace rx
{
class Blit9;
class IndexDataManager;
class ProgramD3D;
class StreamingIndexBufferInterface;
class StaticIndexBufferInterface;
class VertexDataManager;
struct ClearParameters;
struct D3DUniform;
struct TranslatedAttribute;
enum D3D9InitError
......@@ -111,7 +113,8 @@ class Renderer9 : public RendererD3D
const gl::Framebuffer *framebuffer,
bool rasterizerDiscard,
bool transformFeedbackActive) override;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
gl::Error applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) override;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceInfo);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo);
......@@ -258,9 +261,9 @@ class Renderer9 : public RendererD3D
void release();
void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v);
void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v);
void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v);
void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v);
void applyUniformniv(const D3DUniform *targetUniform, const GLint *v);
void applyUniformnbv(const D3DUniform *targetUniform, const GLint *v);
gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
......
......@@ -62,32 +62,31 @@ class ProgramGL : public ProgramImpl
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
void getUniformfv(GLint location, GLfloat *params) override;
void getUniformiv(GLint location, GLint *params) override;
void getUniformuiv(GLint location, GLuint *params) override;
bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) override;
void reset() override;
void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) override;
GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
private:
void reset();
// Helper function, makes it simpler to type.
GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; }
const FunctionsGL *mFunctions;
StateManagerGL *mStateManager;
// A map from uniform location to index of mSamplerBindings and array index of the uniform
struct SamplerLocation
{
size_t samplerIndex;
size_t arrayIndex;
};
std::map<GLint, SamplerLocation> mSamplerUniformMap;
std::vector<GLint> mUniformRealLocationMap;
// An array of the samplers that are used by the program
std::vector<SamplerBindingGL> mSamplerBindings;
// A map from a mData.getUniforms() index to a mSamplerBindings index.
std::vector<size_t> mUniformIndexToSamplerIndex;
GLuint mProgramID;
};
......
......@@ -1145,8 +1145,11 @@ bool ValidateEndQuery(gl::Context *context, GLenum target)
return true;
}
static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType,
GLint location, GLsizei count, LinkedUniform **uniformOut)
static bool ValidateUniformCommonBase(gl::Context *context,
GLenum targetUniformType,
GLint location,
GLsizei count,
const LinkedUniform **uniformOut)
{
if (count < 0)
{
......@@ -1173,16 +1176,16 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform
return false;
}
LinkedUniform *uniform = program->getUniformByLocation(location);
const LinkedUniform &uniform = program->getUniformByLocation(location);
// attempting to write an array to a non-array uniform is an INVALID_OPERATION
if (!uniform->isArray() && count > 1)
if (!uniform.isArray() && count > 1)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
*uniformOut = uniform;
*uniformOut = &uniform;
return true;
}
......@@ -1195,7 +1198,7 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G
return false;
}
LinkedUniform *uniform = NULL;
const LinkedUniform *uniform = nullptr;
if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
{
return false;
......@@ -1230,7 +1233,7 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati
return false;
}
LinkedUniform *uniform = NULL;
const LinkedUniform *uniform = nullptr;
if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
{
return false;
......@@ -1526,7 +1529,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
// Uniform buffer validation
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
{
const gl::UniformBlock *uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding);
......@@ -1545,7 +1548,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
}
if (uniformBufferSize < uniformBlock->dataSize)
if (uniformBufferSize < uniformBlock.dataSize)
{
// undefined behaviour
context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."));
......@@ -1944,8 +1947,8 @@ static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint loca
ASSERT(programObject);
// sized queries -- ensure the provided buffer is large enough
LinkedUniform *uniform = programObject->getUniformByLocation(location);
size_t requiredBytes = VariableExternalSize(uniform->type);
const LinkedUniform &uniform = programObject->getUniformByLocation(location);
size_t requiredBytes = VariableExternalSize(uniform.type);
if (static_cast<size_t>(bufSize) < requiredBytes)
{
context->recordError(Error(GL_INVALID_OPERATION));
......
......@@ -140,7 +140,6 @@
'libANGLE/renderer/FramebufferImpl.h',
'libANGLE/renderer/ImageImpl.h',
'libANGLE/renderer/ImplFactory.h',
'libANGLE/renderer/ProgramImpl.cpp',
'libANGLE/renderer/ProgramImpl.h',
'libANGLE/renderer/QueryImpl.h',
'libANGLE/renderer/RenderbufferImpl.h',
......
......@@ -144,9 +144,12 @@
1031 WIN : dEQP-GLES2.functional.uniform_api.random.41 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.51 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.54 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.61 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.72 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.79 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.82 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.87 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.93 = FAIL
504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.basic_struct.sampler2D_samplerCube_* = FAIL
504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.struct_in_array.sampler2D_samplerCube_* = FAIL
504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.array_in_struct.sampler2D_samplerCube_* = FAIL
......
......@@ -982,11 +982,14 @@
1098 WIN : dEQP-GLES3.functional.uniform_api.random.3 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.6 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.8 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.17 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.20 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.21 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.29 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.54 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.81 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.83 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.87 = FAIL
1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.cond_float = FAIL
1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.max_cond_float = FAIL
1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.cond_vec2 = FAIL
......
......@@ -313,6 +313,51 @@ TEST_P(UniformBufferTest, ManyUniformBufferRange)
}
}
// Tests that active uniforms have the right names.
TEST_P(UniformBufferTest, ActiveUniformNames)
{
const std::string &vertexShaderSource =
"#version 300 es\n"
"in vec2 position;\n"
"out float v;\n"
"uniform blockName {\n"
" float f;\n"
"} instanceName;\n"
"void main() {\n"
" v = instanceName.f;\n"
" gl_Position = vec4(position, 0, 1);\n"
"}";
const std::string &fragmentShaderSource =
"#version 300 es\n"
"precision highp float;\n"
"in float v;\n"
"out vec4 color;\n"
"void main() {\n"
" color = vec4(v, 0, 0, 1);\n"
"}";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
ASSERT_NE(0u, program);
GLint activeUniforms;
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
ASSERT_EQ(1, activeUniforms);
GLint maxLength, size;
GLenum type;
GLsizei length;
glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
std::vector<GLchar> strBuffer(maxLength + 1, 0);
glGetActiveUniform(program, 0, maxLength, &length, &size, &type, &strBuffer[0]);
ASSERT_GL_NO_ERROR();
EXPECT_EQ(1, size);
EXPECT_GLENUM_EQ(GL_FLOAT, type);
EXPECT_EQ("blockName.f", std::string(&strBuffer[0]));
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(UniformBufferTest, ES3_D3D11(), ES3_D3D11_FL11_1(), ES3_D3D11_FL11_1_REFERENCE());
......
......@@ -16,11 +16,7 @@ namespace
class UniformTest : public ANGLETest
{
protected:
UniformTest()
: mProgram(0),
mUniformFLocation(-1),
mUniformILocation(-1),
mUniformBLocation(-1)
UniformTest() : mProgram(0), mUniformFLocation(-1), mUniformILocation(-1), mUniformBLocation(-1)
{
setWindowWidth(128);
setWindowHeight(128);
......@@ -40,7 +36,12 @@ class UniformTest : public ANGLETest
"uniform float uniF;\n"
"uniform int uniI;\n"
"uniform bool uniB;\n"
"void main() { gl_FragColor = vec4(uniF + float(uniI) + (uniB ? 1.0 : 0.0)); }";
"uniform bool uniBArr[4];\n"
"void main() {\n"
" gl_FragColor = vec4(uniF + float(uniI));\n"
" gl_FragColor += vec4(uniB ? 1.0 : 0.0);\n"
" gl_FragColor += vec4(uniBArr[0] ? 1.0 : 0.0);\n"
"}";
mProgram = CompileProgram(vertexShader, fragShader);
ASSERT_NE(mProgram, 0u);
......@@ -169,13 +170,6 @@ TEST_P(UniformTest, UniformArrayLocations)
// Test that float to integer GetUniform rounds values correctly.
TEST_P(UniformTest, FloatUniformStateQuery)
{
// TODO(jmadill): remove this suppression once we support ANGLE-only state queries.
if (isAMD() && (GetParam() == ES2_OPENGL() || GetParam() == ES3_OPENGL()))
{
std::cout << "Skipping test due to a driver bug on AMD." << std::endl;
return;
}
std::vector<GLfloat> inValues;
std::vector<GLfloat> expectedFValues;
std::vector<GLint> expectedIValues;
......@@ -214,7 +208,7 @@ TEST_P(UniformTest, FloatUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index)
{
GLfloat inValue = inValues[index];
GLfloat inValue = inValues[index];
GLfloat expectedValue = expectedFValues[index];
glUniform1f(mUniformFLocation, inValue);
......@@ -226,7 +220,7 @@ TEST_P(UniformTest, FloatUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index)
{
GLfloat inValue = inValues[index];
GLfloat inValue = inValues[index];
GLint expectedValue = expectedIValues[index];
glUniform1f(mUniformFLocation, inValue);
......@@ -240,13 +234,6 @@ TEST_P(UniformTest, FloatUniformStateQuery)
// Test that integer to float GetUniform rounds values correctly.
TEST_P(UniformTest, IntUniformStateQuery)
{
// TODO(jmadill): remove this suppression once we support ANGLE-only state queries.
if ((isAMD() || isIntel()) && (GetParam() == ES2_OPENGL() || GetParam() == ES3_OPENGL()))
{
std::cout << "Skipping test due to a driver bug." << std::endl;
return;
}
std::vector<GLint> inValues;
std::vector<GLint> expectedIValues;
std::vector<GLfloat> expectedFValues;
......@@ -274,7 +261,7 @@ TEST_P(UniformTest, IntUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index)
{
GLint inValue = inValues[index];
GLint inValue = inValues[index];
GLint expectedValue = expectedIValues[index];
glUniform1i(mUniformILocation, inValue);
......@@ -286,7 +273,7 @@ TEST_P(UniformTest, IntUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index)
{
GLint inValue = inValues[index];
GLint inValue = inValues[index];
GLfloat expectedValue = expectedFValues[index];
glUniform1i(mUniformILocation, inValue);
......@@ -301,9 +288,10 @@ TEST_P(UniformTest, IntUniformStateQuery)
TEST_P(UniformTest, BooleanUniformStateQuery)
{
glUseProgram(mProgram);
GLint intValue = 0;
GLint intValue = 0;
GLfloat floatValue = 0.0f;
// Calling Uniform1i
glUniform1i(mUniformBLocation, GL_FALSE);
glGetUniformiv(mProgram, mUniformBLocation, &intValue);
......@@ -320,6 +308,67 @@ TEST_P(UniformTest, BooleanUniformStateQuery)
glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
EXPECT_EQ(1.0f, floatValue);
// Calling Uniform1f
glUniform1f(mUniformBLocation, 0.0f);
glGetUniformiv(mProgram, mUniformBLocation, &intValue);
EXPECT_EQ(0, intValue);
glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
EXPECT_EQ(0.0f, floatValue);
glUniform1f(mUniformBLocation, 1.0f);
glGetUniformiv(mProgram, mUniformBLocation, &intValue);
EXPECT_EQ(1, intValue);
glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
EXPECT_EQ(1.0f, floatValue);
ASSERT_GL_NO_ERROR();
}
// Test queries for arrays of boolean uniforms.
TEST_P(UniformTest, BooleanArrayUniformStateQuery)
{
glUseProgram(mProgram);
GLint intValues[4] = {0};
GLfloat floatValues[4] = {0.0f};
GLint boolValuesi[4] = {0, 1, 0, 1};
GLfloat boolValuesf[4] = {0, 1, 0, 1};
GLint location = glGetUniformLocation(mProgram, "uniBArr");
// Calling Uniform1iv
glUniform1iv(location, 4, boolValuesi);
glGetUniformiv(mProgram, location, intValues);
for (unsigned int idx = 0; idx < 4; ++idx)
{
EXPECT_EQ(boolValuesi[idx], intValues[idx]);
}
glGetUniformfv(mProgram, location, floatValues);
for (unsigned int idx = 0; idx < 4; ++idx)
{
EXPECT_EQ(boolValuesf[idx], floatValues[idx]);
}
// Calling Uniform1fv
glUniform1fv(location, 4, boolValuesf);
glGetUniformiv(mProgram, location, intValues);
for (unsigned int idx = 0; idx < 4; ++idx)
{
EXPECT_EQ(boolValuesi[idx], intValues[idx]);
}
glGetUniformfv(mProgram, location, floatValues);
for (unsigned int idx = 0; idx < 4; ++idx)
{
EXPECT_EQ(boolValuesf[idx], floatValues[idx]);
}
ASSERT_GL_NO_ERROR();
}
......
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