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) ...@@ -69,13 +69,13 @@ inline int clampToInt(unsigned int x)
template <typename DestT, typename SrcT> template <typename DestT, typename SrcT>
inline DestT clampCast(SrcT value) 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 lo = static_cast<SrcT>(std::numeric_limits<DestT>::min());
SrcT hi = static_cast<SrcT>(std::numeric_limits<DestT>::max()); 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); return static_cast<DestT>(value > lo ? (value > hi ? hi : value) : lo);
} }
......
...@@ -26,6 +26,8 @@ struct InterfaceBlock; ...@@ -26,6 +26,8 @@ struct InterfaceBlock;
struct COMPILER_EXPORT BlockMemberInfo struct COMPILER_EXPORT BlockMemberInfo
{ {
BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
: offset(offset), : offset(offset),
arrayStride(arrayStride), arrayStride(arrayStride),
......
...@@ -189,6 +189,16 @@ class Program : angle::NonCopyable ...@@ -189,6 +189,16 @@ class Program : angle::NonCopyable
{ {
return mOutputVariables; 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: private:
friend class Program; friend class Program;
...@@ -205,10 +215,12 @@ class Program : angle::NonCopyable ...@@ -205,10 +215,12 @@ class Program : angle::NonCopyable
std::vector<sh::Attribute> mAttributes; std::vector<sh::Attribute> mAttributes;
std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask; 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 // TODO(jmadill): use unordered/hash map when available
std::map<int, VariableLocation> mOutputVariables; std::map<int, VariableLocation> mOutputVariables;
// TODO(jmadill): move more state into Data.
}; };
Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle); Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
...@@ -251,11 +263,10 @@ class Program : angle::NonCopyable ...@@ -251,11 +263,10 @@ class Program : angle::NonCopyable
GLint getActiveUniformMaxLength(); GLint getActiveUniformMaxLength();
GLint getActiveUniformi(GLuint index, GLenum pname) const; GLint getActiveUniformi(GLuint index, GLenum pname) const;
bool isValidUniformLocation(GLint location) const; bool isValidUniformLocation(GLint location) const;
LinkedUniform *getUniformByLocation(GLint location) const; const LinkedUniform &getUniformByLocation(GLint location) const;
LinkedUniform *getUniformByName(const std::string &name) const;
GLint getUniformLocation(const std::string &name); GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name); GLuint getUniformIndex(const std::string &name) const;
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform2fv(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); void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
...@@ -292,7 +303,7 @@ class Program : angle::NonCopyable ...@@ -292,7 +303,7 @@ class Program : angle::NonCopyable
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; 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 setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
...@@ -330,7 +341,8 @@ class Program : angle::NonCopyable ...@@ -330,7 +341,8 @@ class Program : angle::NonCopyable
static bool linkVaryings(InfoLog &infoLog, static bool linkVaryings(InfoLog &infoLog,
const Shader *vertexShader, const Shader *vertexShader,
const Shader *fragmentShader); 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, bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
const sh::InterfaceBlock &fragmentInterfaceBlock); const sh::InterfaceBlock &fragmentInterfaceBlock);
...@@ -352,6 +364,40 @@ class Program : angle::NonCopyable ...@@ -352,6 +364,40 @@ class Program : angle::NonCopyable
std::vector<const sh::Varying *> getMergedVaryings() const; std::vector<const sh::Varying *> getMergedVaryings() const;
void linkOutputVariables(); 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; Data mData;
rx::ProgramImpl *mProgram; rx::ProgramImpl *mProgram;
......
...@@ -13,55 +13,51 @@ ...@@ -13,55 +13,51 @@
namespace gl namespace gl
{ {
LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, LinkedUniform::LinkedUniform()
const int blockIndex, const sh::BlockMemberInfo &blockInfo) : blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
: 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)
{ {
// 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 bool LinkedUniform::isInDefaultBlock() const
...@@ -72,7 +68,30 @@ bool LinkedUniform::isInDefaultBlock() const ...@@ -72,7 +68,30 @@ bool LinkedUniform::isInDefaultBlock() const
size_t LinkedUniform::dataSize() const size_t LinkedUniform::dataSize() const
{ {
ASSERT(type != GL_STRUCT_ANGLEX); 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 bool LinkedUniform::isSampler() const
...@@ -80,33 +99,48 @@ bool LinkedUniform::isSampler() const ...@@ -80,33 +99,48 @@ bool LinkedUniform::isSampler() const
return IsSamplerType(type); 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) size_t LinkedUniform::getElementSize() const
: name(name),
elementIndex(elementIndex),
dataSize(dataSize),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
{ {
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 @@ ...@@ -12,6 +12,7 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/MemoryBuffer.h"
#include "compiler/translator/blocklayout.h" #include "compiler/translator/blocklayout.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
...@@ -19,53 +20,47 @@ namespace gl ...@@ -19,53 +20,47 @@ namespace gl
{ {
// Helper struct representing a single shader uniform // 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(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(); ~LinkedUniform();
bool isArray() const;
unsigned int elementCount() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
bool isInDefaultBlock() const;
size_t dataSize() const; size_t dataSize() const;
uint8_t *data();
const uint8_t *data() const;
bool isSampler() const; bool isSampler() const;
bool isBuiltIn() const; bool isInDefaultBlock() const;
bool isField() const;
const GLenum type; size_t getElementSize() const;
const GLenum precision; uint8_t *getDataPtrToElement(size_t elementIndex);
const std::string name; const uint8_t *getDataPtrToElement(size_t elementIndex) const;
const unsigned int arraySize;
const int blockIndex;
const sh::BlockMemberInfo blockInfo;
unsigned char *data; int blockIndex;
bool dirty; sh::BlockMemberInfo blockInfo;
unsigned int psRegisterIndex; private:
unsigned int vsRegisterIndex; mutable rx::MemoryBuffer mLazyData;
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;
}; };
// Helper struct representing a single shader uniform block // Helper struct representing a single shader uniform block
struct UniformBlock : angle::NonCopyable struct UniformBlock
{ {
// use GL_INVALID_INDEX for non-array elements UniformBlock();
UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize); UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn);
UniformBlock(const UniformBlock &other) = default;
bool isArrayElement() const; UniformBlock &operator=(const UniformBlock &other) = default;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const; std::string name;
bool isArray;
const std::string name; unsigned int arrayElement;
const unsigned int elementIndex; unsigned int dataSize;
const unsigned int dataSize;
bool vertexStaticUse;
bool fragmentStaticUse;
std::vector<unsigned int> memberUniformIndexes; std::vector<unsigned int> memberUniformIndexes;
......
...@@ -6,32 +6,24 @@ ...@@ -6,32 +6,24 @@
// queryconversions.cpp: Implementation of state query cast conversions // queryconversions.cpp: Implementation of state query cast conversions
#include "libANGLE/queryconversions.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "common/utilities.h" #include "common/utilities.h"
namespace gl namespace gl
{ {
// Helper class for converting a GL type to a GLenum: namespace
// 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;
static GLint64 ExpandFloatToInteger(GLfloat value) GLint64 ExpandFloatToInteger(GLfloat value)
{ {
return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0); return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0);
} }
template <typename QueryT> 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 min = static_cast<GLint64>(std::numeric_limits<QueryT>::min());
const GLint64 max = static_cast<GLint64>(std::numeric_limits<QueryT>::max()); const GLint64 max = static_cast<GLint64>(std::numeric_limits<QueryT>::max());
...@@ -41,8 +33,8 @@ static QueryT ClampToQueryRange(GLint64 value) ...@@ -41,8 +33,8 @@ static QueryT ClampToQueryRange(GLint64 value)
template <typename QueryT, typename NativeT> template <typename QueryT, typename NativeT>
QueryT CastStateValueToInt(GLenum pname, NativeT value) QueryT CastStateValueToInt(GLenum pname, NativeT value)
{ {
GLenum queryType = CastStateValueEnum<QueryT>::mEnumForType; GLenum queryType = GLTypeToGLenum<QueryT>::value;
GLenum nativeType = CastStateValueEnum<NativeT>::mEnumForType; GLenum nativeType = GLTypeToGLenum<NativeT>::value;
if (nativeType == GL_FLOAT) if (nativeType == GL_FLOAT)
{ {
...@@ -72,18 +64,37 @@ QueryT CastStateValueToInt(GLenum pname, NativeT value) ...@@ -72,18 +64,37 @@ QueryT CastStateValueToInt(GLenum pname, NativeT value)
template <typename QueryT, typename NativeT> template <typename QueryT, typename NativeT>
QueryT CastStateValue(GLenum pname, NativeT value) QueryT CastStateValue(GLenum pname, NativeT value)
{ {
GLenum queryType = CastStateValueEnum<QueryT>::mEnumForType; GLenum queryType = GLTypeToGLenum<QueryT>::value;
switch (queryType) switch (queryType)
{ {
case GL_INT: return CastStateValueToInt<QueryT, NativeT>(pname, value); case GL_INT:
case GL_INT_64_ANGLEX: return CastStateValueToInt<QueryT, NativeT>(pname, value); return CastStateValueToInt<QueryT, NativeT>(pname, value);
case GL_FLOAT: return static_cast<QueryT>(value); case GL_INT_64_ANGLEX:
case GL_BOOL: return static_cast<QueryT>(value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE); return CastStateValueToInt<QueryT, NativeT>(pname, value);
default: UNREACHABLE(); return 0; 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> template <typename QueryT>
void CastStateValues(Context *context, GLenum nativeType, GLenum pname, void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
unsigned int numParams, QueryT *outParams) unsigned int numParams, QueryT *outParams)
......
...@@ -6,8 +6,25 @@ ...@@ -6,8 +6,25 @@
// queryconversions.h: Declaration of state query cast conversions // 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 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 // The GL state query API types are: bool, int, uint, float, int64
template <typename QueryT> template <typename QueryT>
...@@ -15,3 +32,5 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname, ...@@ -15,3 +32,5 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
unsigned int numParams, QueryT *outParams); 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 ...@@ -23,16 +23,17 @@ namespace rx
struct LinkResult struct LinkResult
{ {
LinkResult(bool linkSuccess, const gl::Error &error) : linkSuccess(linkSuccess), error(error) {}
bool linkSuccess; bool linkSuccess;
gl::Error error; gl::Error error;
LinkResult(bool linkSuccess, const gl::Error &error);
}; };
class ProgramImpl : angle::NonCopyable class ProgramImpl : angle::NonCopyable
{ {
public: public:
ProgramImpl(const gl::Program::Data &data); ProgramImpl(const gl::Program::Data &data) : mData(data) {}
virtual ~ProgramImpl(); virtual ~ProgramImpl() {}
virtual int getShaderVersion() const = 0; virtual int getShaderVersion() const = 0;
...@@ -65,41 +66,16 @@ class ProgramImpl : angle::NonCopyable ...@@ -65,41 +66,16 @@ class ProgramImpl : angle::NonCopyable
virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; 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 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 // 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. // determine if they can be removed from this interface.
virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0; virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0;
const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; } // Gather uniform block active uniform indices, and uniform block offset info.
const std::map<GLuint, gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; } virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; } std::vector<gl::LinkedUniform> *uniforms) = 0;
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();
protected: protected:
const gl::Program::Data &mData; 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 @@ ...@@ -20,13 +20,6 @@
#include "libANGLE/renderer/d3d/DynamicHLSL.h" #include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" #include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
namespace gl
{
struct LinkedUniform;
struct VariableLocation;
struct VertexFormat;
}
namespace rx namespace rx
{ {
class RendererD3D; class RendererD3D;
...@@ -39,6 +32,43 @@ class ShaderExecutableD3D; ...@@ -39,6 +32,43 @@ class ShaderExecutableD3D;
#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
#endif #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 class ProgramD3D : public ProgramImpl
{ {
public: public:
...@@ -73,13 +103,12 @@ class ProgramD3D : public ProgramImpl ...@@ -73,13 +103,12 @@ class ProgramD3D : public ProgramImpl
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override; LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, 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(); void initializeUniformStorage();
gl::Error applyUniforms(); gl::Error applyUniforms();
gl::Error applyUniformBuffers(const gl::Data &data); gl::Error applyUniformBuffers(const gl::Data &data);
void assignUniformBlockRegister(gl::UniformBlock *uniformBlock,
GLenum shader,
unsigned int registerIndex,
const gl::Caps &caps);
void dirtyAllUniforms(); void dirtyAllUniforms();
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
...@@ -104,15 +133,9 @@ class ProgramD3D : public ProgramImpl ...@@ -104,15 +133,9 @@ class ProgramD3D : public ProgramImpl
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix4x3fv(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 &getVertexUniformStorage() const { return *mVertexUniformStorage; }
const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
void reset();
unsigned int getSerial() const; unsigned int getSerial() const;
void sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes, void sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
...@@ -175,19 +198,24 @@ class ProgramD3D : public ProgramImpl ...@@ -175,19 +198,24 @@ class ProgramD3D : public ProgramImpl
GLenum textureType; GLenum textureType;
}; };
bool defineUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap;
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, void assignUniformRegisters();
sh::HLSLBlockEncoder *encoder); void assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform);
bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps); void assignUniformRegisters(const ShaderD3D *shader,
bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); const sh::ShaderVariable &uniform,
static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, const std::string &fullName,
std::vector<Sampler> &outSamplers, GLuint *outUsedRange); sh::HLSLBlockEncoder *encoder);
void assignAllSamplerRegisters();
void assignSamplerRegisters(const D3DUniform *d3dUniform);
void defineUniformBlocks(const gl::Caps &caps); static void AssignSamplers(unsigned int startSamplerIndex,
void defineUniformBlock(const gl::Shader &shader, GLenum samplerType,
const sh::InterfaceBlock &interfaceBlock, unsigned int samplerCount,
const gl::Caps &caps); std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
size_t defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, BlockInfoMap *blockInfoOut);
template <typename T> template <typename T>
void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
...@@ -195,23 +223,19 @@ class ProgramD3D : public ProgramImpl ...@@ -195,23 +223,19 @@ class ProgramD3D : public ProgramImpl
template <int cols, int rows> template <int cols, int rows>
void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); 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, LinkResult compileProgramExecutables(gl::InfoLog &infoLog,
int registers, int registers,
const std::vector<PackedVarying> &packedVaryings); const std::vector<PackedVarying> &packedVaryings);
void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings); void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location);
void initSemanticIndex(); void initSemanticIndex();
void initAttributesByLayout(); void initAttributesByLayout();
void reset();
RendererD3D *mRenderer; RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL; DynamicHLSL *mDynamicHLSL;
...@@ -259,6 +283,7 @@ class ProgramD3D : public ProgramImpl ...@@ -259,6 +283,7 @@ class ProgramD3D : public ProgramImpl
gl::InputLayout mCachedInputLayout; gl::InputLayout mCachedInputLayout;
std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings; std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
std::vector<D3DUniform *> mD3DUniforms;
static unsigned int issueSerial(); static unsigned int issueSerial();
static unsigned int mCurrentSerial; static unsigned int mCurrentSerial;
......
...@@ -37,8 +37,10 @@ class DebugAnnotator; ...@@ -37,8 +37,10 @@ class DebugAnnotator;
namespace rx namespace rx
{ {
struct D3DUniform;
class ImageD3D; class ImageD3D;
class IndexBuffer; class IndexBuffer;
class ProgramD3D;
class RenderTargetD3D; class RenderTargetD3D;
class ShaderExecutableD3D; class ShaderExecutableD3D;
class SwapChainD3D; class SwapChainD3D;
...@@ -157,7 +159,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D ...@@ -157,7 +159,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
const gl::Framebuffer *framebuffer, const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool rasterizerDiscard,
bool transformFeedbackActive) = 0; 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 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 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; 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, ...@@ -2095,7 +2095,8 @@ gl::Error Renderer11::applyShaders(gl::Program *program,
return gl::Error(GL_NO_ERROR); 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 totalRegisterCountVS = 0;
unsigned int totalRegisterCountPS = 0; unsigned int totalRegisterCountPS = 0;
...@@ -2103,26 +2104,25 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto ...@@ -2103,26 +2104,25 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
bool vertexUniformsDirty = false; bool vertexUniformsDirty = false;
bool pixelUniformsDirty = 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; totalRegisterCountVS += uniform->registerCount;
vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty); vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
} }
if (uniform.isReferencedByFragmentShader() && !uniform.isSampler()) if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
{ {
totalRegisterCountPS += uniform.registerCount; totalRegisterCountPS += uniform->registerCount;
pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty); pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
} }
} }
const ProgramD3D *programD3D = GetAs<ProgramD3D>(&program); const UniformStorage11 *vertexUniformStorage =
const UniformStorage11 *vertexUniformStorage = GetAs<UniformStorage11>(&programD3D->getVertexUniformStorage()); GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
const UniformStorage11 *fragmentUniformStorage = GetAs<UniformStorage11>(&programD3D->getFragmentUniformStorage()); const UniformStorage11 *fragmentUniformStorage =
GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage());
ASSERT(vertexUniformStorage); ASSERT(vertexUniformStorage);
ASSERT(fragmentUniformStorage); ASSERT(fragmentUniformStorage);
...@@ -2150,26 +2150,26 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto ...@@ -2150,26 +2150,26 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
mapPS = (float(*)[4])map.pData; 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 // we assume that uniforms from structs are arranged in struct order in our uniforms list.
// overwrite previously written regions of memory. // otherwise we would overwrite previously written regions of memory.
if (uniform->isReferencedByVertexShader() && mapVS) if (uniform->isReferencedByVertexShader() && mapVS)
{ {
memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data,
} uniform->registerCount * sizeof(float) * componentCount);
}
if (uniform->isReferencedByFragmentShader() && mapPS) if (uniform->isReferencedByFragmentShader() && mapPS)
{ {
memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); 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 ...@@ -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 // 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 // needed for the point sprite geometry shader
if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
......
...@@ -137,7 +137,8 @@ class Renderer11 : public RendererD3D ...@@ -137,7 +137,8 @@ class Renderer11 : public RendererD3D
bool rasterizerDiscard, bool rasterizerDiscard,
bool transformFeedbackActive) override; 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 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); 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; void applyTransformFeedbackBuffers(const gl::State &state) override;
......
...@@ -1910,46 +1910,45 @@ gl::Error Renderer9::applyShaders(gl::Program *program, ...@@ -1910,46 +1910,45 @@ gl::Error Renderer9::applyShaders(gl::Program *program,
return gl::Error(GL_NO_ERROR); 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) switch (targetUniform->type)
{ {
case GL_SAMPLER_2D: case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE: case GL_SAMPLER_CUBE:
break; break;
case GL_BOOL: case GL_BOOL:
case GL_BOOL_VEC2: case GL_BOOL_VEC2:
case GL_BOOL_VEC3: case GL_BOOL_VEC3:
case GL_BOOL_VEC4: case GL_BOOL_VEC4:
applyUniformnbv(targetUniform, i); applyUniformnbv(targetUniform, i);
break; break;
case GL_FLOAT: case GL_FLOAT:
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3: case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4: case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2: case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3: case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4: case GL_FLOAT_MAT4:
applyUniformnfv(targetUniform, f); applyUniformnfv(targetUniform, f);
break; break;
case GL_INT: case GL_INT:
case GL_INT_VEC2: case GL_INT_VEC2:
case GL_INT_VEC3: case GL_INT_VEC3:
case GL_INT_VEC4: case GL_INT_VEC4:
applyUniformniv(targetUniform, i); applyUniformniv(targetUniform, i);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
}
} }
} }
...@@ -1964,7 +1963,7 @@ gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector ...@@ -1964,7 +1963,7 @@ gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector
return gl::Error(GL_NO_ERROR); 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()) if (targetUniform->isReferencedByFragmentShader())
{ {
...@@ -1977,7 +1976,7 @@ void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat ...@@ -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); ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
...@@ -1993,7 +1992,7 @@ void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v ...@@ -1993,7 +1992,7 @@ void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v
applyUniformnfv(targetUniform, (GLfloat*)vector); 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); ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
......
...@@ -32,10 +32,12 @@ namespace rx ...@@ -32,10 +32,12 @@ namespace rx
{ {
class Blit9; class Blit9;
class IndexDataManager; class IndexDataManager;
class ProgramD3D;
class StreamingIndexBufferInterface; class StreamingIndexBufferInterface;
class StaticIndexBufferInterface; class StaticIndexBufferInterface;
class VertexDataManager; class VertexDataManager;
struct ClearParameters; struct ClearParameters;
struct D3DUniform;
struct TranslatedAttribute; struct TranslatedAttribute;
enum D3D9InitError enum D3D9InitError
...@@ -111,7 +113,8 @@ class Renderer9 : public RendererD3D ...@@ -111,7 +113,8 @@ class Renderer9 : public RendererD3D
const gl::Framebuffer *framebuffer, const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool rasterizerDiscard,
bool transformFeedbackActive) override; 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 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 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); 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 ...@@ -258,9 +261,9 @@ class Renderer9 : public RendererD3D
void release(); void release();
void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v); void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v);
void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); void applyUniformniv(const D3DUniform *targetUniform, const GLint *v);
void applyUniformnbv(gl::LinkedUniform *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 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); gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
......
...@@ -62,32 +62,31 @@ class ProgramGL : public ProgramImpl ...@@ -62,32 +62,31 @@ class ProgramGL : public ProgramImpl
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override; 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 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; 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; GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const; const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
private: private:
void reset();
// Helper function, makes it simpler to type.
GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; }
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
// A map from uniform location to index of mSamplerBindings and array index of the uniform std::vector<GLint> mUniformRealLocationMap;
struct SamplerLocation
{
size_t samplerIndex;
size_t arrayIndex;
};
std::map<GLint, SamplerLocation> mSamplerUniformMap;
// An array of the samplers that are used by the program // An array of the samplers that are used by the program
std::vector<SamplerBindingGL> mSamplerBindings; std::vector<SamplerBindingGL> mSamplerBindings;
// A map from a mData.getUniforms() index to a mSamplerBindings index.
std::vector<size_t> mUniformIndexToSamplerIndex;
GLuint mProgramID; GLuint mProgramID;
}; };
......
...@@ -1145,8 +1145,11 @@ bool ValidateEndQuery(gl::Context *context, GLenum target) ...@@ -1145,8 +1145,11 @@ bool ValidateEndQuery(gl::Context *context, GLenum target)
return true; return true;
} }
static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType, static bool ValidateUniformCommonBase(gl::Context *context,
GLint location, GLsizei count, LinkedUniform **uniformOut) GLenum targetUniformType,
GLint location,
GLsizei count,
const LinkedUniform **uniformOut)
{ {
if (count < 0) if (count < 0)
{ {
...@@ -1173,16 +1176,16 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform ...@@ -1173,16 +1176,16 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform
return false; 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 // 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)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
*uniformOut = uniform; *uniformOut = &uniform;
return true; return true;
} }
...@@ -1195,7 +1198,7 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G ...@@ -1195,7 +1198,7 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G
return false; return false;
} }
LinkedUniform *uniform = NULL; const LinkedUniform *uniform = nullptr;
if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform)) if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
{ {
return false; return false;
...@@ -1230,7 +1233,7 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati ...@@ -1230,7 +1233,7 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati
return false; return false;
} }
LinkedUniform *uniform = NULL; const LinkedUniform *uniform = nullptr;
if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform)) if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
{ {
return false; return false;
...@@ -1526,7 +1529,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz ...@@ -1526,7 +1529,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
// Uniform buffer validation // Uniform buffer validation
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++) 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); GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding); const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding);
...@@ -1545,7 +1548,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz ...@@ -1545,7 +1548,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize()); uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
} }
if (uniformBufferSize < uniformBlock->dataSize) if (uniformBufferSize < uniformBlock.dataSize)
{ {
// undefined behaviour // undefined behaviour
context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.")); 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 ...@@ -1944,8 +1947,8 @@ static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint loca
ASSERT(programObject); ASSERT(programObject);
// sized queries -- ensure the provided buffer is large enough // sized queries -- ensure the provided buffer is large enough
LinkedUniform *uniform = programObject->getUniformByLocation(location); const LinkedUniform &uniform = programObject->getUniformByLocation(location);
size_t requiredBytes = VariableExternalSize(uniform->type); size_t requiredBytes = VariableExternalSize(uniform.type);
if (static_cast<size_t>(bufSize) < requiredBytes) if (static_cast<size_t>(bufSize) < requiredBytes)
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
......
...@@ -140,7 +140,6 @@ ...@@ -140,7 +140,6 @@
'libANGLE/renderer/FramebufferImpl.h', 'libANGLE/renderer/FramebufferImpl.h',
'libANGLE/renderer/ImageImpl.h', 'libANGLE/renderer/ImageImpl.h',
'libANGLE/renderer/ImplFactory.h', 'libANGLE/renderer/ImplFactory.h',
'libANGLE/renderer/ProgramImpl.cpp',
'libANGLE/renderer/ProgramImpl.h', 'libANGLE/renderer/ProgramImpl.h',
'libANGLE/renderer/QueryImpl.h', 'libANGLE/renderer/QueryImpl.h',
'libANGLE/renderer/RenderbufferImpl.h', 'libANGLE/renderer/RenderbufferImpl.h',
......
...@@ -144,9 +144,12 @@ ...@@ -144,9 +144,12 @@
1031 WIN : dEQP-GLES2.functional.uniform_api.random.41 = FAIL 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.51 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.54 = 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.72 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.79 = 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.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.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.struct_in_array.sampler2D_samplerCube_* = FAIL
504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.array_in_struct.sampler2D_samplerCube_* = FAIL 504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.array_in_struct.sampler2D_samplerCube_* = FAIL
......
...@@ -982,11 +982,14 @@ ...@@ -982,11 +982,14 @@
1098 WIN : dEQP-GLES3.functional.uniform_api.random.3 = FAIL 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.6 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.8 = 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.20 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.21 = 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.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.81 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.83 = 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.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.max_cond_float = FAIL
1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.cond_vec2 = FAIL 1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.cond_vec2 = FAIL
......
...@@ -313,6 +313,51 @@ TEST_P(UniformBufferTest, ManyUniformBufferRange) ...@@ -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. // 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()); ANGLE_INSTANTIATE_TEST(UniformBufferTest, ES3_D3D11(), ES3_D3D11_FL11_1(), ES3_D3D11_FL11_1_REFERENCE());
......
...@@ -16,11 +16,7 @@ namespace ...@@ -16,11 +16,7 @@ namespace
class UniformTest : public ANGLETest class UniformTest : public ANGLETest
{ {
protected: protected:
UniformTest() UniformTest() : mProgram(0), mUniformFLocation(-1), mUniformILocation(-1), mUniformBLocation(-1)
: mProgram(0),
mUniformFLocation(-1),
mUniformILocation(-1),
mUniformBLocation(-1)
{ {
setWindowWidth(128); setWindowWidth(128);
setWindowHeight(128); setWindowHeight(128);
...@@ -40,7 +36,12 @@ class UniformTest : public ANGLETest ...@@ -40,7 +36,12 @@ class UniformTest : public ANGLETest
"uniform float uniF;\n" "uniform float uniF;\n"
"uniform int uniI;\n" "uniform int uniI;\n"
"uniform bool uniB;\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); mProgram = CompileProgram(vertexShader, fragShader);
ASSERT_NE(mProgram, 0u); ASSERT_NE(mProgram, 0u);
...@@ -169,13 +170,6 @@ TEST_P(UniformTest, UniformArrayLocations) ...@@ -169,13 +170,6 @@ TEST_P(UniformTest, UniformArrayLocations)
// Test that float to integer GetUniform rounds values correctly. // Test that float to integer GetUniform rounds values correctly.
TEST_P(UniformTest, FloatUniformStateQuery) 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> inValues;
std::vector<GLfloat> expectedFValues; std::vector<GLfloat> expectedFValues;
std::vector<GLint> expectedIValues; std::vector<GLint> expectedIValues;
...@@ -214,7 +208,7 @@ TEST_P(UniformTest, FloatUniformStateQuery) ...@@ -214,7 +208,7 @@ TEST_P(UniformTest, FloatUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index) for (size_t index = 0; index < inValues.size(); ++index)
{ {
GLfloat inValue = inValues[index]; GLfloat inValue = inValues[index];
GLfloat expectedValue = expectedFValues[index]; GLfloat expectedValue = expectedFValues[index];
glUniform1f(mUniformFLocation, inValue); glUniform1f(mUniformFLocation, inValue);
...@@ -226,7 +220,7 @@ TEST_P(UniformTest, FloatUniformStateQuery) ...@@ -226,7 +220,7 @@ TEST_P(UniformTest, FloatUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index) for (size_t index = 0; index < inValues.size(); ++index)
{ {
GLfloat inValue = inValues[index]; GLfloat inValue = inValues[index];
GLint expectedValue = expectedIValues[index]; GLint expectedValue = expectedIValues[index];
glUniform1f(mUniformFLocation, inValue); glUniform1f(mUniformFLocation, inValue);
...@@ -240,13 +234,6 @@ TEST_P(UniformTest, FloatUniformStateQuery) ...@@ -240,13 +234,6 @@ TEST_P(UniformTest, FloatUniformStateQuery)
// Test that integer to float GetUniform rounds values correctly. // Test that integer to float GetUniform rounds values correctly.
TEST_P(UniformTest, IntUniformStateQuery) 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> inValues;
std::vector<GLint> expectedIValues; std::vector<GLint> expectedIValues;
std::vector<GLfloat> expectedFValues; std::vector<GLfloat> expectedFValues;
...@@ -274,7 +261,7 @@ TEST_P(UniformTest, IntUniformStateQuery) ...@@ -274,7 +261,7 @@ TEST_P(UniformTest, IntUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index) for (size_t index = 0; index < inValues.size(); ++index)
{ {
GLint inValue = inValues[index]; GLint inValue = inValues[index];
GLint expectedValue = expectedIValues[index]; GLint expectedValue = expectedIValues[index];
glUniform1i(mUniformILocation, inValue); glUniform1i(mUniformILocation, inValue);
...@@ -286,7 +273,7 @@ TEST_P(UniformTest, IntUniformStateQuery) ...@@ -286,7 +273,7 @@ TEST_P(UniformTest, IntUniformStateQuery)
for (size_t index = 0; index < inValues.size(); ++index) for (size_t index = 0; index < inValues.size(); ++index)
{ {
GLint inValue = inValues[index]; GLint inValue = inValues[index];
GLfloat expectedValue = expectedFValues[index]; GLfloat expectedValue = expectedFValues[index];
glUniform1i(mUniformILocation, inValue); glUniform1i(mUniformILocation, inValue);
...@@ -301,9 +288,10 @@ TEST_P(UniformTest, IntUniformStateQuery) ...@@ -301,9 +288,10 @@ TEST_P(UniformTest, IntUniformStateQuery)
TEST_P(UniformTest, BooleanUniformStateQuery) TEST_P(UniformTest, BooleanUniformStateQuery)
{ {
glUseProgram(mProgram); glUseProgram(mProgram);
GLint intValue = 0; GLint intValue = 0;
GLfloat floatValue = 0.0f; GLfloat floatValue = 0.0f;
// Calling Uniform1i
glUniform1i(mUniformBLocation, GL_FALSE); glUniform1i(mUniformBLocation, GL_FALSE);
glGetUniformiv(mProgram, mUniformBLocation, &intValue); glGetUniformiv(mProgram, mUniformBLocation, &intValue);
...@@ -320,6 +308,67 @@ TEST_P(UniformTest, BooleanUniformStateQuery) ...@@ -320,6 +308,67 @@ TEST_P(UniformTest, BooleanUniformStateQuery)
glGetUniformfv(mProgram, mUniformBLocation, &floatValue); glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
EXPECT_EQ(1.0f, 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(); 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